泛型类型参数和动态类型
本文关键字:类型 动态 泛型类型参数 | 更新日期: 2023-09-27 18:14:10
我想知道,在下面的例子中,TrickyGenericMethod
中的if
语句是一个坏主意,还是在某些情况下它是可以的。在我的例子中,我有一个工厂方法,它使用泛型参数来产生正确的结果。不幸的是,如果传入的对象的类型引用是对接口或抽象类的引用,则会产生错误的结果,因为T
不是对象的实际类型。
class Program
{
static void Main(string[] args)
{
HasGenericMethod hgm = new HasGenericMethod();
Console.WriteLine(hgm.GenericMehtod("string"));
Console.WriteLine(hgm.GenericMehtod((object)"object"));
Console.WriteLine();
Console.WriteLine(hgm.TrickyGenericMethod("string"));
Console.WriteLine(hgm.TrickyGenericMethod((object)"object"));
Console.ReadKey();
}
}
class HasGenericMethod
{
public string GenericMehtod<T>(T param)
{
return "Type of T:'t" + typeof(T) + "'tType of param:'t" + param.GetType();
}
public string TrickyGenericMethod<T>(T param)
{
if (typeof(T) != param.GetType())
{
return TrickyGenericMethod((dynamic)param);
}
return "Type of T:'t" + typeof(T) + "'tType of param:'t" + param.GetType(); ;
}
}
是TrickyGenericMethod中的if语句
是一个坏主意
是的,在我看来是这样。特别是,如果您使用内部类型的值从不同的程序集调用它(并且它经过此路径一次),"执行时间编译器"将使用dynamic
调用的最佳可访问类型……所以你最终会得到一个堆栈溢出。
编辑:示例代码…
// Library.cs
using System;
public class Library
{
public static void Foo<T>(T value)
{
Console.WriteLine("{0} : {1}", typeof(T), value.GetType());
if (typeof(T) != value.GetType())
{
dynamic d = value;
Foo(d);
}
}
}
// Test.cs
class Internal {}
class Program
{
static void Main(string[] args)
{
Library.Foo<object>(new Internal());
}
}
结果:System.Object : Internal
System.Object : Internal
...
System.Object : Internal
Process is terminated due to StackOverflowException.
可能还有其他类似的情况,它也不能完全工作。我会尽量避免依赖typeof(T) == value.GetType()
。
您可以无条件地使用动态类型调用私有实现方法,这样您最终只尝试一次,并以"尽力而为"的方法结束。
首先,这是一个坏主意,因为你以一种不必要的方式使用递归,你最多有一个其他调用,所以为什么要递归,一个私有的助手方法会更清晰,更少出错。
第二,您正在测试何时T将等于GetType()
并递归直到它,因此只需直接使用GetType()
的结果并完成它。