簡體   English   中英

使用接口轉換為泛型類

[英]Casting to a generic class with interface

更新了MarcinJuraszek的輸入

我有一種感覺,我在這里碰到了一個共同/逆向差異問題,但我不確定我是否理解如何修復它。 我有一個這樣的課:

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屬性的類:

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

現在我的問題是我無法將SomeClass<MyEnum, MyImplementation>分配給MyProp屬性,因為我在運行時收到InvalidCastException ,抱怨它無法將SomeClass<MyEnum, MyImplementation> InvalidCastExceptionSomeClass<MyEnum, MyImplementation> SomeClass<MyEnum, IMyInterface>

我該如何解決這個問題?

例如,這不編譯:

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

這是一個小點網小提琴

您可以通過使泛型類型參數不變(協變或逆變,取決於其成員)來使其工作。 但是,在C#中,您只能聲明接口上不變的泛型參數,因此您必須聲明另一個接口:

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; }
}

這將使以下代碼編譯:

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

另一種可能的解決方案是使用另一個接口,其中S泛型類型參數不存在:

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; }
}

獎金 - 為什么它不起作用:

讓我們假設您的代碼編譯,只要T實現IT ,您就可以將MyClass<T>分配給MyClass<IT> 你可以有以下課程:

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

並做

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

使用該instance.MyProp List<MyInterfaceImplementation>將是List<MyInterfaceImplementation>但您可以訪問它,就像它是List<IMyInterface>因此您可以嘗試添加MyOtherInterfaceImplementation元素,這會在運行時崩潰。 不好玩。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM