Jam*_*esH 4 .net c# casting interface
我刚刚遇到了我认为类型转换的奇怪之处.我有类似以下代码:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
当它到达DoSomething(classSet)时,编译器会抱怨它无法将HashSet <MyClass>强制转换为ICollection <IMyClass>.这是为什么?HashSet实现了ICollection,MyClass实现了IMyClass,那么为什么不能使用强制转换?
顺便说一句,这并不难解决,认为它有点尴尬.
void Main()
{
HashSet<MyClass> classSet = FillMyClassSet();
HashSet<IMyClass> interfaceSet = new HashSet<IMyClass>();
foreach(IMyClass item in classSet)
{
interfaceSet.Add(item);
}
DoSomething(interfaceSet);
}
Run Code Online (Sandbox Code Playgroud)
对我来说,这个作品的事实使得无法施展更加神秘.
它不会工作,因为所有实例MyClass的存在IMyClass并不自动意味着的所有实例HashSet<MyClass>也HashSet<IMyClass>.如果有效,你可以:
ICollection<IMyClass> h = new HashSet<MyClass>();
h.Add(new OtherClassThatImplementsIMyClass()); // BOOM!
Run Code Online (Sandbox Code Playgroud)
从技术上讲,它不起作用,因为C#(<= 3.0)泛型是不变的.C#4.0引入了安全协方差,在这种情况下也无济于事.但是,当接口仅在输入中使用类型参数或仅在输出位置使用类型参数时,它确实有帮助.例如,您将能够将a HashSet<MyClass>作为一个IEnumerable<IMyClass>方法传递给某个方法.
顺便说一句,它们比手动填充另一个更容易解决方法HashSet:
var newSet = new HashSet<IMyClass>(originalSet);
Run Code Online (Sandbox Code Playgroud)
或者,Cast如果要将集合强制转换为IEnumerable<IMyClass>:
IEnumerable<IMyClass> sequence = set.Cast<IMyClass>(set);
Run Code Online (Sandbox Code Playgroud)