使用c#4和VS 2010是否可以实现?我正在对实现通用接口的类进行一些处理,并且在处理之后想要将对象转换为更简单的接口,以便我可以提取由公共接口定义的某些属性。
interface IMyInterface
{
public Id { get; set; }
}
interface IFile<T1, T2> where T1 : IMyInterface where T2 : IMyInterface
{
Int64 prop1 { get; set; }
T1 t1 { get; set; }
T2 t2 { get; set; }
}
ClassA : IMyInterface
{
... Implement some properties plus interface
public Id { get; set; }
}
ClassB : IMyInterface
{
... Implement some properties plus interface
public Id { get; set; }
}
例如,这个类有ClassX和ClassY我想成为处理/保存的某些类型,但之后我只想提取像ID一样的常见属性,这在实现这个通用接口的所有类中很常见(其他属性)在t1,t1中不常见
ClassSomething : IFile<ClassA, ClassB>
{
... Implement properties plus interface
public ClassX t1
{ get {} set {} }
public ClassY t2
{ get {} set {} }
}
IList<IFile<TItem1, TItem2>> list = new List<IFile<TItem1, TItem2>>()
ClassA ca = new ClassA();
... Fill in the interface defined properties
... Fill the list with objects of ClassSomething
foreach (IFile<TItem1, TItem2> x in list)
{
// This fails
IFile<IMyInterface, IMyInterface> interfaceItem =
(IFile<IMyInterface, IMyInterface>)x;
}
将x
以上(t1
和t2
属性专门针对)更简单的IMyInterface
接口转换为失败。
有很多通用界面问题,但我没有看到(或认出?)任何解决方案。
答案 0 :(得分:5)
您正在寻找的解决方案称为variance(协方差和逆变)。但是,IMyInterface
和T1
中的T2
无法提供协变或逆变,因为它有公共getter和公共setter接受T1
和T2
:< / p>
interface IAnimal {}
class Dog : IAnimal { public void Bark () ; }
class Cat : IAnimal { public void Meow () ; }
var dogs = new FileImpl<Dog, Dog> () ;
dogs.t1 = new Dog () ;
var file = (IFile<IAnimal, IAnimal>) dogs ; // if this were OK...
file.t1 = new Cat () ; // this would have to work
dogs.t1.Bark () ; // oops, t1 is a cat now
答案 1 :(得分:2)
只是为了扩展Anton Tykhyy的回答,
是的,如果您愿意/能够对您的IFile界面进行以下更改,您可以使用C#4实现此目的:
interface IFile<out T1, out T2> where T1 : IMyInterface where T2 : IMyInterface
{
Int64 prop1 { get; set; }
T1 t1 { get; }
T2 t2 { get; }
}
我已将out
关键字添加到通用参数中,并且我已从t1和t2属性中删除了set;
。
答案 2 :(得分:1)
为什么不访问x.T1
和x.T2
,然后将其转换为IMyInterface
?
foreach (IFile<TItem1, TItem2> x in list)
{
var t1 = x.T1 as IMyInterface;
var t2 = x.T2 as IMyInterface;
}
答案 3 :(得分:1)
我认为你将通用约束与继承混淆了。一个与另一个无关。泛型接口的约束是编译器指令,它告诉编译器泛型参数必须满足特定的要求。从逻辑上讲,对我们来说,这意味着ClassSomething
肯定有IMyInterface
的实现。但这就是我们,编译器不会将这些约束转换为任何类型的继承映射,因此它仍然只知道它是实现ClassSomething
的{{1}}实例。因此,它不会让您直接将其转换为IFile<ClassA, ClassB>
。