铸造用接口的通用类 [英] Casting to a generic class with interface

查看:112
本文介绍了铸造用接口的通用类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

与输入更新从MarcinJuraszek

我有一种感觉,我碰到一个合作/潮水变化问题就在这里,但我不能确定我知道如何解决它。我有这样一个类:

I have a feeling I'm bumping into a co / contra variance problem here, but I'm not sure I understand how to fix it. I have a class like this:

public interface ISomeClass<TEnum, out S>
{
     TEnum Dim { get; }
     IEnumerable<S> Inc { get; }
}

public class SomeClass<TEnum, S> : ISomeClass<TEnum, S>
    where TEnum : struct, IConvertible
    where S : IMyInterface
{
    public TEnum Dim { get; set; }
    public IEnumerable<S> Inc { get; set; }
}

和我有一个类实现 IMyInterface的

public class MyImplementation : IMyInterface
{

}

和,当然,我有一个 SomeClass的属性:

And, of course, I have a class with a SomeClass property:

public class MyContainer<TEnum> where TEnum : struct, IConvertible
{
    public SomeClass<TEnum, IMyInterface> MyProp { get; set; }
}

现在我的问题是,我不能指定一个 SomeClass的< MyEnum,MyImplementation> MyProp 属性,因为我得到一个 InvalidCastException的在运行时抱怨说,它不能投的 SomeClass的< MyEnum,MyImplementation> SomeClass的< MyEnum,IMyInterface的>

Now my problem is that I can't assign a SomeClass<MyEnum, MyImplementation> to the MyProp property because I get an InvalidCastException at runtime complaining that it can't cast the SomeClass<MyEnum, MyImplementation> to SomeClass<MyEnum, IMyInterface>.

我要如何解决这个

例,这并不编译:

var c = new MyContainer<MyEnum>();
c.MyProp = new SomeClass<MyEnum, MyImplementation>();

下面是一个的点网小提琴

推荐答案

您可以把它通过让您的工作泛型类型参数不变的(无论是协变或逆变,这取决于它的成员)。然而,在C#中你只能声明接口不变泛型参数,所以你必须声明另一个接口:

You can make it work by having your generic type parameter invariant (either covariant or contravariant, depending on its members). However, in C# you can only declare generic parameters invariant on interface, so you'd have to declare another interface:

public interface ISomeClass<TEnum, in S>
{

}

public class SomeClass<TEnum, S> : ISomeClass<TEnum, IMyInterface>
    where TEnum : struct, IConvertible
    where S : IMyInterface
{

}

public class MyContainer<TEnum> where TEnum : struct, IConvertible
{
    public ISomeClass<TEnum, IMyInterface> MyProp { get; set; }
}

这会使下面的代码编译:

That would make following code compile:

var container = new MyContainer<DayOfWeek>();
container.MyProp = new SomeClass<DayOfWeek, MyImplementation>();



另一种可能的解决方案将是使用另一个接口,其中取值泛型类型参数不存在:

Another possible solution would be to use another interface, where S generic type parameter doesn't exist:

public interface ISomeClass<TEnum>
    where TEnum: struct, IConvertible
{

}

public class SomeClass<TEnum, S> : ISomeClass<TEnum>
    where TEnum : struct, IConvertible
    where S : IMyInterface
{

}

public class MyContainer<TEnum> where TEnum : struct, IConvertible
{
    public ISomeClass<TEnum> MyProp { get; set; }
}



奖金 - 因为它为什么没有按' ŧ工作:

Bonus - as of why it doesn't work:

让我们想象一下,你的代码编译,并且你可以将 MyClass的< T> MyClass的< IT> 只要 T 工具 IT 。你可以有下面的类:

Let's imagine that your code compiles, and you can assign MyClass<T> to MyClass<IT> as long as T implements IT. You could have following class:

class MyClass<T>
{
    public List<T> MyProp { get; set; }
}

和做

MyClass<IMyInterface> instance = new MyClass<MyInterfaceImplementation>();



instance.MyProp 列表< MyInterfaceImplementation> ,但你有机会访问它,就好像它是列表< IMyInterface的> 所以你可以尝试添加的元素 MyOtherInterfaceImplementation 将导致程序崩溃在运行时。不好玩。

with that instance.MyProp would be List<MyInterfaceImplementation> but you had access to it as if it was List<IMyInterface> so you could try adding element of MyOtherInterfaceImplementation which would crash at runtime. Not fun.

这篇关于铸造用接口的通用类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆