[英]C# casting to object in interface generic
我有一个问题,我不明白在通用接口中进行转换(可能因为协方差和逆变在我看来并不完全清楚)。
我有一个接口,我定义了一个getter和setter,它应该以类型的方式接受任何东西(没有对象作为类型)例如:
public interface IDummy <T>
{
int SomeCommonMethod() ;
T Anything { get; set; }
}
现在我定义一些之前定义的接口的混凝土实现。
public class MyStrObj : IDummy <string>
{
private string _stirngVal = string.Empty ;
public int SomeCommonMethod()
{
return 0 ;
}
public string Anything
{
get { return _stirngVal ; }
set { _stirngVal = value ; }
}
}
public class MyFileObj : IDummy <File>
{
private File _file = null ;
public int SomeCommonMethod()
{
return 0 ;
}
public File Anything
{
get { return _file ; }
set { _file = value ; }
}
}
在所有时间都按预期工作,但现在当尝试使用这两个对象时,他们的行为开始变得让我困惑。
我尝试定义一个应该能够使用以前的类的对象(无论它们在泛型中具有哪种类型,它们是IDummy的重要性)。
public class Consumer
{
public static void Consume ( IDummy<object> obj )
{
//SOME CODE HERE.
}
}
现在,如果我尝试这个代码:
MyStrObj obj = new MyStrObj () ;
Consumer.Consume ( obj ) ;
然后编译器通知我,在Consume方法调用(obj sure)上有一些无效参数,但是这里没有隐式转换?
如果我这样尝试:
MyStrObj obj = new MyStrObj () ;
Consumer.Consume ( (IDummy<object>)obj ) ;
编译似乎工作,因为我认为它应该(当时我还没有测试两个调用是否相同)。
提前感谢任何可以帮助我理解这种行为的人,并对我的英语(不是我的语言)感到抱歉。
你的IDummy<T>
不协变。 这就是为什么这种隐式转换不起作用的原因。 如果它是协变的,那么从更具体的泛型类型到更普遍的类型的转换将起作用。 但是在您的示例中,您无法使接口协变IDummy<out T>
,因为它具有带有泛型参数的属性设置器。
Consumer
类中的方法必须是通用的。
public class Consumer
{
public static void Consume<T> ( IDummy<T> obj )
{
//SOME CODE HERE.
}
}
那你可以做
var foo = new MyStrObj();
foo.Anything = "Hello";
Consumer.Consume(foo);
为了实现您使用协方差描述的内容,您需要修改您的界面以使其协变。
协方差允许您将更具体的类型分配给不太具体的类型。 但这仅适用于仅返回模板类型对象的类。
因此,在您的界面中,您需要删除setter ant,使用关键字out
将T标记为协变。 您可以将setter保留在实现它的类上。 所以你的界面必须如下所示:
public interface IDummy<out T>
{
int SomeCommonMethod();
T Anything { get; }
}
您的MyStrObj
, MyFileObj
和Consumer
类可以保持原样。 更改后,您可以在调用Consume方法时使用协方差。
MyStrObj obj = new MyStrObj();
obj.Anything = "My string";
Consumer.Consume(obj);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.