c#转换为接口泛型中的对象
本文关键字:对象 泛型 接口 转换 | 更新日期: 2023-09-27 18:04:47
我有一个问题,我不理解在泛型接口中的强制转换(可能是因为协方差和逆变对我来说目前还不完全清楚)。
我有一个接口,我定义了一个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 ) ;
然后编译器通知我,有一些无效的参数超过消费方法调用(obj确定),但这里没有隐式强制转换?
如果我尝试这样做:
MyStrObj obj = new MyStrObj () ;
Consumer.Consume ( (IDummy<object>)obj ) ;
编译器似乎像我想象的那样工作(有时我没有测试这两个调用是否等效)。
提前感谢任何可以帮助我理解这种行为的人,并为我的英语(不是我的语言)感到抱歉。
您的IDummy<T>
不是协变的。这就是为什么这种隐性转换不起作用的原因。如果它是协变的,那么从更具体的泛型到更一般的类型的转换就会有效。然而,在你的例子中,你不能让你的接口协变IDummy<out T>
,因为它有一个属性setter与你的通用参数。
您的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并使用关键字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);