问题 转换没有特定类型的泛型类


我有以下泛型类

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?
    }
}

我是否可以在不指定类的泛型类型的情况下进行转换?


12820
2018-01-04 14:49


起源



答案:


如果你确定参数 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.
    }
}

9
2018-01-04 14:53





如果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;
        ...
    }
}

4
2018-01-04 15:29





如何使功能通用?

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; }
}

1
2018-01-04 14:54





您是否尝试将方法定义更改为此类似的内容?

public void DoSomething<T>(Home<T> x)
{

}

0
2018-01-04 14:54





我知道这是一个旧帖子,但到目前为止发布的所有答案都没有直接解决这个问题,而只是建议解决方法(即“使用反射”,“让你的 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;
    }
}

0
2017-07-28 14:29