在通用方法中,您需要将返回变量强制转换为对象,然后返回到泛型类型,我理解为什么通常这样,但是我不明白为什么当您需要时,为什么需要这样做? #39;已经确定了变量在return语句范围内的类型。例如,通常我会这样做:
public MyType1 obj1;
public MyType2 obj2;
public T GetObject<T>()
{
if (obj1 is T) return (T)(object)obj1;
else if (obj2 is T) return (T)(object)obj2;
else return default(T);
}
但我的问题是,为什么我不能像这样删除演员:
public MyType1 obj1;
public MyType2 obj2;
public T GetObject<T>()
{
if (obj1 is T) return obj1;
else if (obj2 is T) return obj2;
else return default(T);
}
为什么编译器不能理解该对象是唯一的类型?
答案 0 :(得分:3)
您对泛型做出了错误的假设。为了更好地理解这一点,想象一下。假设您有一个基类Base和两个子类Sub和VerySub。
如果您的成员存储为Base,则编译器只能保证它们是Base。它是泛型使用的静态打字系统。在运行时,让我们说我们有一个名为GetIfVerySub的简单函数。让我们说它对Base类型的对象进行了测试,并发现它也是一个VerySub。这在编译时是不可知的,所以为了返回下载的对象,你会期望做一个演员或一个as。
这正是你的泛型函数正在尝试做的事情,但由于它是通用的,它也可以在任何类型上工作,包括与Base不兼容的类型。
但更好的问题是你为什么要这样做?
答案 1 :(得分:3)
根据C# Reference:
是关键字会导致编译时警告,如果已知表达式始终为 true 或始终为 false ,但通常在运行时评估类型兼容性。
这是obj1
类型T
是否由编译器确定,但在代码运行时进行评估。
答案 2 :(得分:1)
避免使用foo is T; (T)foo
个表达式。使用as
运算符可以解决您的问题:
public MyType1 obj1;
public T GetObject<T>() where T : class {
T ret = obj1 as T;
if( ret != null ) return ret;
ret = obj2 as T;
if( ret != null ) return ret;
return default(T);
}