我有以下泛型类
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?
}
}
我是否可以在不指定类的泛型类型的情况下进行转换?
如果你确定参数 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.
}
}
如果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;
...
}
}
如何使功能通用?
public void DoSomething<T>(object x)
{
if(x is Home<T>)
{
x as Home<T> ...
}
}
编辑:
另一种可能性是创建一个保存属性的接口 GetClassName
所以你只需要检查它是否属于那个界面。
public interface IDescribeClass
{
public string GetClassName { get; set; }
}
顺便说一句:我会使用完整的合格名称
public string ClassType
{
get{ return typeof(T).FullName; }
}
您是否尝试将方法定义更改为此类似的内容?
public void DoSomething<T>(Home<T> x)
{
}
我知道这是一个旧帖子,但到目前为止发布的所有答案都没有直接解决这个问题,而只是建议解决方法(即“使用反射”,“让你的 DoSomething()
方法泛型“或”创建非泛型基类并调用此基类'方法')。
我是否可以在不指定类的泛型类型的情况下进行转换?
所以要清楚地回答你的问题: 不,这是不可能的。因为 协方差约束 在C#中你不能强制转换为泛型类。
更详细:我假设你想要使用 x as Home<object>
作为最低的共同标准,以便能够打电话 toString()
由...提供 Object
类。铸造你的 object x
至 Home<object>
将需要协方差,这是类不可能的(只有通用接口和委托可以协变)。虽然这很棒 在编译时防止错误当你想要访问泛型类的方法时,这肯定是一种烦恼,就像你的情况一样。 @ n8wrl答案可能是你在“演员”方面的最佳镜头。
话虽这么说,你也可以使用基于接口的解决方案 出旗 在你的T参数:
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;
}
}