显式强制转换存在,但似乎不适用于Dictionary <int,string [] =“”>到IDictionary <int,ienumerable <string =“”>&gt; </int,> </int,>

时间:2011-12-14 18:03:18

标签: c#

使用隐式强制转换编写代码会生成CS0266

Dictionary<Int32, string[]> d1 = new Dictionary<int, string[]>();
IDictionary<int, IEnumerable<string>> ide1 = d1; // CS0266

显式强制转换存在的提示暗示明确的强制转换会解决问题。

IDictionary<int, IEnumerable<string>> ide1 = (IDictionary<int, IEnumerable<string>>)d1; // No error, but throws an exception

有没有办法让这个演员表演?它适用于string[][]IEnumerable<IEnumerable<string>>吗?

namespace Quickie
{
    class QuickieArray
    {
        private static void TestCastDictionaryWithArrayValue()
        {
            Console.WriteLine();
            Console.WriteLine("===TestCastDictionaryWithArrayValue===");
            Dictionary<Int32, string[]> d1 = new Dictionary<int, string[]>();
            d1[1] = new string[]{"foo"};
            IDictionary<int, string[]> id1 = d1;
            Console.WriteLine("id1 is null: {0}", id1 == null);
            IDictionary<int, IEnumerable<string>> ide1 = id1 as IDictionary<int, IEnumerable<string>>;
            IDictionary<int, IEnumerator<string>> iden1 = id1 as IDictionary<int, IEnumerator<string>>;
            Console.WriteLine("ide1 is null: {0}", ide1 == null);
            Console.WriteLine("iden1 is null: {0}", iden1 == null);

            Console.WriteLine();
        }
        internal static void Test()
        {
            Console.WriteLine();
            Console.WriteLine("=QuickieArray=");
            TestCastDictionaryWithArrayValue();
        }
    }
}

输出:

  

=== TestCastDictionaryWithArrayValue ===
  id1为null:False
  ide1为null:True   iden1为null:True

4 个答案:

答案 0 :(得分:7)

这是一个经典的协方差/逆转问题。我将向您展示一个简化示例,以证明为什么Dictionary<Int32, string[]> 一个IDictionary<int, IEnumerable<string>>不能强制转换为一个。

让我们假装有问题的演员表工作并且这段代码编译:

Dictionary<int, string[]> arrayDictionary = new Dictionary<int, string[]>();
IDictionary<int, IEnumerable<string>> enumerableDictionary = arrayDictionary;

现在,我们有一个对象。它显然属于Dictionary<int, string[]>类型。我们有两个引用,一个是Dictionary<int, string[]>类型,另一个是IDictionary<int, IEnumerable<string>>类型。

如果遵循此代码会发生什么?

List<string> stringList = new List<string>();
enumerableDictionary.Add(0, stringList);

如果我们可以按照您想要的方式强制转换Dictionary<int, string[]>,上面的代码片段就会成功编译......

......然后在运行时爆炸。 为什么?因为List<string> 不是 string[]

enumerableDictionary的{​​{1}}方法接受任何Add,但创建的真实对象(IEnumerable<string>)有一个方法接受Dictionary<int, string[]>

这就是为什么string[] 一个Dictionary<Int32, string[]>不能强制转换为一个。

答案 1 :(得分:6)

没有演员,也不应该。想象一下:

        Dictionary<Int32, string[]> d1 = new Dictionary<int, string[]>();
        IDictionary<int, IEnumerable<string>> ide1 = d1; 
        ide1.Add(99,new List<string>());

虽然IDictionary<int, IEnumerable<string>>完全可以接受第三行,但IDictionary<int, string[]>无法接受。

答案 2 :(得分:1)

正如@adam-maras和@ d-stanley所说,这是一个协方差问题。因此,尽可能使用接口。例如,使用IDictionary<Int32, IEnumerable<string>>作为较少派生的类型,保存使用更多派生类型实例化的数据:

using System;
using System.Collections.Generic;

namespace Quickie
{
    class QuickieArray
    {
        private static void TestCastIDictionaryWithArrayValue()
        {
            Console.WriteLine();
            Console.WriteLine("===TestCastIDictionaryWithArrayValue===");
            IDictionary<int, IEnumerable<string>> d1 = new Dictionary<int, IEnumerable<string>>();
            d1[1] = new string[] { "foo" };
            IDictionary<int, IEnumerable<string>> id1 = d1;
            Console.WriteLine("id1 is null: {0}", id1 == null);
            IDictionary<int, IEnumerable<string>> ide1 = id1 as IDictionary<int, IEnumerable<string>>;
            IDictionary<int, IEnumerator<string>> iden1 = id1 as IDictionary<int, IEnumerator<string>>;
            Console.WriteLine("ide1 is null: {0}", ide1 == null);
            Console.WriteLine("iden1 is null: {0}", iden1 == null);

            Console.WriteLine();
        }

        internal static void Test()
        {
            Console.WriteLine();
            TestCastIDictionaryWithArrayValue();
        }
    }
}

就现有的明确演员而言?不,它没有。

答案 3 :(得分:0)

这样的东西也可以作为我的例子中的一个例子我从逗号分隔字段中读取

var intFileCount = 0;
Dictionary<int, string[]> dctListRecords = null; 
//initialize a capacity if you want 
dctListRecords = new Dictionary<int, string[]>(strLinesStockRecord.Count());
foreach (string strLineSplit in strLinesStockRecord)
{
  lstSplitList2 = strLineSplit.Split(chrCOMMA_SEP).ToList();
  dctListRecords.Add(intFileCount, lstSplitList2.ToArray());
  //this allows you to use the string value inside of string[]
  lstSplitList2.Clear();
  intFileCount++;
}