如果您需要将泛型类型参数强制转换为特定类型,我们可以将其转换为对象并执行如下所示的转换,
void SomeMethod(T t)
{
SomeClass obj2 = (SomeClass)(object)t;
}
是否有更好的方法来实现这一目标,而不是将其转换为对象,然后再转换为特定类型。
问题
我有一个泛型函数接受泛型类型参数,在函数内部基于类型检查我做了一些操作,如下面
void SomeMethod(T t)
{
if (typeof(T).Equals(typeof(TypeA)))
{
TypeA = (TypeA)(object)t;
//Do some operation
}
else if (typeof(T).Equals(typeof(TypeB)))
{
TypeB = (TypeB)(object)t;
//Do some operation
}
}
答案 0 :(得分:5)
更好的设计是对它进行约束,这种约束在类型T和您希望在方法中期望的类之间是常见的,在本例中为SomeClass
。
class SomeConsumer<T> where T : ISomeClass
{
void SomeMethod(T t)
{
ISomeClass obj2 = (ISomeClass) t;
}
}
interface ISomeClass{}
class SomeClass : ISomeClass {}
这是糟糕的设计。尝试将“操作”移动到类本身中,以便调用者不必知道类型。如果不可能分享更多正在做的事情,那么你想要完成的是你没有一堆if / else语句,其中执行取决于传递给方法的对象类型。
class SomeConsumer<T> where T : ISomeClass
{
void SomeMethod(T t)
{
ISomeClass obj2 = (ISomeClass) t;
// execute
t.Operation();
}
}
interface ISomeClass{
void Operation();
}
class SomeClass : ISomeClass {
public void Operation(){/*execute operation*/}
}
答案 1 :(得分:5)
您可以使用Convert.ChangeType
SomeClass obj2 = (SomeClass)Convert.ChangeType(t, typeof(SomeClass));
尽管如此,请记住,如果演员表无效,这将引发异常。
答案 2 :(得分:3)
使用as
:
SomeClass obj2 = t as SomeClass;
这不会抛出异常,如果转换失败,t
将为null。
我真的不知道你要做什么,但我希望你不要错过Generics的观点。
如果您打算将方法限制为键入SomeClass
和后代:
void SomeMethod(T t) where T : SomeClass
答案 3 :(得分:1)
您可以as
使用该案例
void SomeMethod(T t)
{
SomeClass obj2 = t as SomeClass;
}
答案 4 :(得分:1)
如果输入类型T
与目标类型TypeA
或TypeB
(使用参数约束)之间没有关系,我们正在纯粹关注铸造问题,答案很简单:
不,没有比你正在使用的方法更好的方法!!!
我同意其他人的意见,如果你在这个对象上做更多的操作,你可能想选择不同的设计。
答案 5 :(得分:1)
偶然发现此问题,并想为后来发现此问题的任何人提供最新答案。在较新的C#版本(我撰写本文时为8.0)中,pattern matching将允许您以更加简洁的方式执行此操作:
void SomeMethod<T>(T t)
{
switch(t)
{
case TypeA a:
// Do some operation using a.
Console.WriteLine($"{a} is a TypeA!");
break;
case TypeB b:
// Do some operation using b.
Console.WriteLine($"{b} is a TypeB!");
break;
default:
// Handle this case.
Console.WriteLine("I don't know what this type is.");
break;
}
}
这将检查对象的类型,如果找到匹配项,则将其一步分配给指定的变量,然后在该情况下可以使用该变量。 (您也可以在if语句中执行类似的操作:if (t is TypeA a) a.DoSomething(); ...
)
话虽如此,我也同意其他答复,即您应该尽可能地限制这一点(void SomeMethod<T>(T t) where T : ISomeInterface {...}
),或者在可能的情况下将操作移至要测试的类中。
答案 6 :(得分:0)
我知道这是一个迟到的问题,但在这里你可以做什么
一个很好的选择是使你的函数接受类object
的参数,并根据需要做你的开关案例
只需进行投射
YourClass = (YourClass) parameterObject;