我刚刚遇到了我认为类型转换中的一个奇怪问题。我有类似于以下的代码:
interface IMyClass { }
class MyClass: IMyClass { }
class Main
{
void DoSomething(ICollection<IMyClass> theParameter) { }
HashSet<MyClass> FillMyClassSet()
{
//Do stuff
}
void Main()
{
HashSet<MyClass> classSet = FillMyClassSet();
DoSomething(classSet);
}
}
当它到达 DoSomething(classSet) 时,编译器提示它无法将 HashSet
顺便说一句,这并不难解决,只是觉得有点尴尬。
void Main()
{
HashSet<MyClass> classSet = FillMyClassSet();
HashSet<IMyClass> interfaceSet = new HashSet<IMyClass>();
foreach(IMyClass item in classSet)
{
interfaceSet.Add(item);
}
DoSomething(interfaceSet);
}
对我来说,这个有效的事实让无法转换变得更加神秘。
最佳答案
它不会工作,因为 MyClass
的所有实例正在IMyClass
不会自动暗示 HashSet<MyClass>
的所有实例也是HashSet<IMyClass>
.如果有效,您可以:
ICollection<IMyClass> h = new HashSet<MyClass>();
h.Add(new OtherClassThatImplementsIMyClass()); // BOOM!
从技术上讲,它不起作用,因为 C# (<= 3.0) 泛型是不变的。 C# 4.0 引入了安全协变,这在这种情况下也无济于事。但是,当接口(interface)仅在输入位置或仅在输出位置使用类型参数时,它确实有帮助。例如,您将能够传递 HashSet<MyClass>
作为IEnumerable<IMyClass>
一些方法。
顺便说一下,它们比手动填充另一个 HashSet
更容易。喜欢:
var newSet = new HashSet<IMyClass>(originalSet);
或者您可以使用 Cast
方法,如果你想将一个集合转换为 IEnumerable<IMyClass>
:
IEnumerable<IMyClass> sequence = set.Cast<IMyClass>(set);
关于C# 类型转换怪癖 - 接口(interface)作为泛型类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2104802/