我有以下通用类
public class Home<T> where T : Class
{
public string GetClassType
{
get{ return T.ToString() }
}
}
现在,我得到一个对象X,我肯定知道它是Home:
public void DoSomething(object x)
{
if(x is // Check if Home<>)
{
// I want to invoke GetClassType method of x
// but I don't know his generic type
x as Home<?> // What should I use here?
}
}
我是否可以在不指定类的泛型类型的情况下进行转换?
答案 0 :(得分:9)
如果您确定DoSomething
的参数是Home<T>
,为什么不将其作为通用方法?
public void DoSomething<T>(Home<T> home)
{
...
}
当然,如果DoSomething
在逻辑上应该是Home<T>
上的实例方法,那就更容易了。
如果确实想要坚持使用你拥有的东西,你可以使用反射(未经测试):
public void DoSomething(object x)
{
// null checks here.
Type t = x.GetType();
if (t.IsGenericType &&
&& t.GetGenericTypeDefinition() == typeof(Home<>))
{
string result = (string) t.GetProperty("GetClassType")
.GetValue(x, null);
Console.WriteLine(result);
}
else
{
... // do nothing / throw etc.
}
}
答案 1 :(得分:4)
如果Home派生自基类怎么办?
public class Home
{
public virtual string GetClassType { get; }
}
public class Home<T> : Home
where T : class
{
public override string GetClassType
{
get{ return T.ToString() }
}
...
}
然后
public void DoSomething(object x)
{
if(x is Home)
{
string ct = ((Home)x).GetClassType;
...
}
}
答案 2 :(得分:1)
如何使函数通用?
public void DoSomething<T>(object x)
{
if(x is Home<T>)
{
x as Home<T> ...
}
}
编辑:
另一种可能性是创建一个包含属性GetClassName
的接口,因此您只需要检查它是否属于该接口。
public interface IDescribeClass
{
public string GetClassName { get; set; }
}
BTW:我会使用完全限定名称
public string ClassType
{
get{ return typeof(T).FullName; }
}
答案 3 :(得分:0)
您是否尝试过将方法定义更改为此类内容?
public void DoSomething<T>(Home<T> x)
{
}
答案 4 :(得分:0)
我知道这是一个旧主题,但是到目前为止,所有发布的答案都没有直接解决此问题,而只是建议的解决方法(即“使用反射”,“使DoSomething()
方法通用”或“创建非-通用基类并调用此基类的“方法”)。
是否可以在不指定类的泛型类型的情况下进行转换?
因此要明确回答您的问题:否。由于C#中的covariance constraints,您不能转换为通用类。
更详细:我假设您想使用x as Home<object>
作为最低的公共分母,以便能够调用toString()
类提供的Object
。将您的object x
强制转换为Home<object>
会需要协方差,而对于类而言,这是不可能的(只有通用接口和委托可以是协方差)。尽管这对prevent mistakes at compile time来说是很棒的,但是当您想要访问通用类上的方法时,确实很烦人。就“投射”而言,@ n8wrl答案可能是您最好的选择。
话虽如此,您还可以使用T参数上的out flag来寻求基于接口的解决方案:
interface IHome<out T> {
string GetClassType { get; }
}
public class Home<T> : IHome<T> where T : class
{
public string GetClassType
{
get { return typeof(T).Name; }
}
}
然后这应该工作:
public void DoSomething(object x)
{
if(x is // Check if Home<>)
{
var y = x as IHome<object>;
var z = y.GetClassType;
}
}