gpt4 book ai didi

c# - 从 Generics 转换为特定子类

转载 作者:太空狗 更新时间:2023-10-29 18:07:56 25 4
gpt4 key购买 nike

我有一个类

public class MyClass<T> where T : OneType
{
T MyObj { get; set; }

public MyCLass(T obj)
{
}
}

public class SubClass: MyClass<TwoType>
{
}

// snip for other similar class definition

其中,TwoType 派生自 OneType

现在,我有了这个实用方法

public static MyClass<T> Factory<T>(T vd)
where T : OneType
{
switch(vd.TypeName)
{
case Constant.TwoType
return new SubClass((TwoType)vd);
// snip for other type check
}
}

很明显,哪个函数检查vd 的类型,然后创建一个合适的MyClass 类型。唯一的问题是上面的代码无法编译,我不知道为什么

错误是

Cannot cast expression of T to TwoType

最佳答案

正如 Grzenio 正确指出的那样,类型 T 的表达式不能转换为 TwoType。编译器不知道表达式保证为 TwoType 类型——这是由您的“if”语句保证的,但编译器在分析类型时不考虑 if 语句的含义。相反,编译器假定 T 可以是满足约束的任何类型,包括 ThreeType,一种从 OneType 而不是 TwoType 派生的类型。显然没有从 ThreeType 到 TwoType 的转换,因此也没有从 T 到 TwoType 的转换。

您可以通过说“好吧,将 T 视为对象,然后将对象转换为 TwoType”来欺骗编译器允许它。沿途的每一步都是合法的——T 可以转换为对象,并且可能存在从对象到 TwoType 的转换,因此编译器允许它。

从 SubClass 转换为 MyClass<T> 时,您会遇到同样的问题.同样,您可以通过首先转换为对象来解决问题。

但是,这段代码仍然是错误的:

public static MyClass<T> Factory<T>(T vd) 
where T:OneType
{
switch(vd.TypeName)
{
case Constant.TwoType
// WRONG
return (MyClass<T>)(object)(new SubClass((TwoType)(object)vd));
// snip for other type check
}
}

为什么错了?好吧,考虑一下这里可能出现的所有问题。例如:你说

class AnotherTwoType : TwoType { }
...
x = Factory<TwoType>(new AnotherTwoType());

会发生什么?我们不调用 SubClass 构造函数,因为参数不完全是 TwoType 类型,它是从 TwoType 派生的类型。而不是开关,你可能想要

public static MyClass<T> Factory<T>(T vd) 
where T:OneType
{
if (vd is TwoType)
// STILL WRONG
return (MyClass<T>)(object)(new SubClass((TwoType)(object)vd));
// snip for other type check
}

这仍然是错误的。再一次,想想可能会出什么问题:

x = Factory<OneType>(new TwoType());

现在发生了什么?参数是 TwoType,我们创建一个新的 SubClass,然后尝试将其转换为 MyClass<OneType> , 但没有从 SubClass 到 MyClass<OneType> 的转换所以这会在运行时崩溃和死亡。

你工厂的正确代码是

public static MyClass<T> Factory<T>(T vd) 
where T:OneType
{
if (vd is TwoType && typeof(T) == typeof(TwoType))
return (MyClass<T>)(object)(new SubClass((TwoType)(object)vd));
// snip for other type check
}

现在一切都清楚了吗?您可能会考虑完全不同的方法; 当您需要这么多的强制转换和运行时类型检查来让编译器相信代码是正确的时,这就证明整个事情都是糟糕的代码味道。

关于c# - 从 Generics<T> 转换为特定子类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2028310/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com