使用泛型类型进行显式转换

时间:2018-11-29 07:36:36

标签: c# generics type-conversion

我有一个代码段:

public interface IMyInternalClass
{
}

public class MyInternalClass : IMyInternalClass
{
}

public interface IMyClass
{
    T GetInternalObject<T>();
}

public class MyClass: IMyClass
{
    private readonly MyInternalClass _internalObject;

    public T GetInternalObject<T>()
    {
        return (T)(IMyInternalClass)_internalObject;
    }

    public MyClass(MyInternalClass internalObject)
    {
        _internalObject = internalObject;
    }
}

GetInternalObject<T>的用法:

IMyInternalClass internalObject = myClass?.GetInternalObject<IMyInternalClass>();

如果我尝试通过return (T)_internalObject;使用显式转换-它将不起作用,并且将失败,并显示错误“ 无法将类型'MyInternalClass'转换为'T'

因此,在不影响此代码示例的设计的情况下,为什么我要先将其显式转换为(IMyInternalClass)呢?

  

还有另一个问题Cannot convert type: why is it necesssary to cast twice?,但没有关于接口使用情况的信息,例如   在这种情况下。

1 个答案:

答案 0 :(得分:4)

  

为什么首先需要强制转换为object

_internalObject的类型为MyInternalClass,而您正在尝试将其强制转换为TT可以是任何类型,因此编译器认为:“我敢肯定您肯定不能将MyInternalClass转换为任何类型。”如果首先将其强制转换为object,则编译器会认为“类型object的值在运行时可以是任何类型,因此可以强制转换为任何类型。”

如果您不满意,这是使用该规范的另一种解释。

根据C#规范的第6.2.7节“涉及类型参数的显式转换”:

  

明确的参考转化

     

对于给定的类型参数T,存在以下显式转换:

     
      
  • 从T的有效基类C到T,以及从C的任何基类C到T。在运行时,如果T是值类型,则转换将作为拆箱转换执行。否则,该转换将作为显式引用转换或标识转换执行。
  •   
  • 从任何接口类型到T。在运行时,如果T是值类型,则转换将作为拆箱转换执行。否则,该转换将作为显式引用转换或标识转换执行。
  •   
  • ...
  •   

T的有效基类是object,这就是为什么您可以执行此强制转换。


也就是说,您在这里所做的事情似乎是个坏主意。此代码非常不安全。您可以将任何类型传递给T,但只有objectIMyInternalClassMyInternalClass之类的东西才能用于T

因此,这似乎是对泛型的滥用。您应该只返回MyInternalClassIMyInternalClass

public MyInternalClass GetInternalObject()
{
    return _internalObject;
}
// or
public IMyInternalClass GetInternalObject()
{
    return _internalObject;
}