繁体   English   中英

C#在接口泛型中转换为对象

[英]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; }
}

您的MyStrObjMyFileObjConsumer类可以保持原样。 更改后,您可以在调用Consume方法时使用协方差。

    MyStrObj obj = new MyStrObj();
    obj.Anything = "My string";
    Consumer.Consume(obj);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM