【问题标题】:C# determining generic typeC# 确定泛型类型
【发布时间】:2011-02-24 18:57:35
【问题描述】:

我有几个模板化的对象都实现了相同的接口:

I.E.

MyObject<datatype1> obj1;
MyObject<datatype2> obj2;
MyObject<datatype3> obj3;

我想将这些对象存储在列表中...我想我会这样做:

private List<MyObject<object>> _myList;

然后我想创建一个带有 1 个参数的函数,它是一种数据类型,以查看使用该数据类型的对象是否存在于我的列表中......有点无能为力。在伪代码中是:

public bool Exist(DataType T)
{
   return (does _myList contain a MyObject<T>?);
}

一些澄清......

我的界面是IMyObject&lt;T&gt;,我的对象是MyObject&lt;T&gt;。我有一个新类MyObjectManager,我需要在其中存储一个MyObject&lt;T&gt; 列表。我需要一个函数来检查该列表中是否存在MyObject&lt;T&gt;T 类型是使用 T4 自动生成的数据类型......来自我的实体数据模型的 POCO 类。

【问题讨论】:

  • 如果它包含一个MyObject&lt;U&gt;U继承T怎么办?
  • 我的 U 是使用 T4 和 EF POCO 类自动生成的。
  • 类是否相互继承?
  • 不,默认情况下它们不继承任何东西。

标签: c# generics reflection types


【解决方案1】:

你可以做一个泛型函数:

public bool Exists<T>() where T : class {
    return _myList.OfType<MyObject<T>>().Any();
}

请注意,这要求您在编译时知道T

如果您在运行时只有一个 System.Type 对象,则需要使用反射:

public bool Exists(Type t) {
    var objectOfT = typeof(MyObject<>).MakeGenericType(t);

    return _myList.Any(o => o.GetType() == objectOfT);
}

但是请注意,List&lt;MyObject&lt;object&gt;&gt; 不能拥有MyObject&lt;SomeType&gt;
您需要将列表更改为List&lt;object&gt;,或者使MyObject 实现或继承非泛型类型并使列表包含该类型。

【讨论】:

  • 我的存储列表的类将没有泛型类型,但是 MyObject 中的 T 在编译时是已知的,并且在此类中引用了这些对象的命名空间。当我尝试您的第一个示例时,它说类型 T 必须是引用类型才能将其用作参数。我希望 T 成为泛型类型,因此我可以传入任何数据类型,无论是 int、string 等
  • 您需要添加一个where T : class 约束,以匹配MyObject 中的约束。
【解决方案2】:

既然它们都实现了相同的接口,那么与其将它们转换为对象并调用 GetType(这可能很昂贵),为什么不在接口中添加一个名为类名(或其他东西)的属性呢?然后您可以使用 linq 来获取该属性。别忘了using System.Linq

using System.Linq;

public bool Exist(List<IMyInterface> objects, IMyInterface typeToCheck)
{
   return objects.Any(t => t.ObjectName == typeToCheck.ObjectName);
}

【讨论】:

  • 我的界面是IMyInterface
【解决方案3】:

扩展方法怎么样?

public static bool HasAny(this IEnumerable source, Type type) {
    foreach (object item in source)
        if (item != null && item.GetType().Equals(type))
            return true;

    return false;
}

用法:

bool hasDataType1 = myList.HasAny(typeof(MyObject<datatype1>));

请注意,如果您不想输入 typeof(...) - 即,如果您基本上希望您的 Exist 方法关心 MyObject&lt;T&gt; 类型的对象,我会选择 SLaks 的回答:

public static bool Exist<T>(this IEnumerable source) {
    return source.OfType<MyObject<T>>().Any();
}

另外,SLaks 是对的,你真的不能有一个 List&lt;MyObject&lt;object&gt;&gt;,除了 MyObject&lt;object&gt; 类型的对象或某些派生类之外的任何东西(以及 MyObject&lt;datatype1&gt; 等。 strong> 派生自 MyObject&lt;object&gt; -- 泛型不能那样工作)。

我可能建议解决整个“如果不使用反射就无法使用System.Type 对象获取泛型类的类型”问题的另一种方法是:让你的MyObject&lt;T&gt; 实现非泛型界面,像这样:

public interface IMyObject {
    Type DataType { get; }
}

public class MyObject<T> : IMyObject<T>, IMyObject {
    public Type DataType {
        get { return typeof(T); }
    }
}

那么您的列表可能是List&lt;IMyObject&gt;(非通用接口),您的Exist 方法可能如下所示:

public static bool Exist<T>(this IEnumerable source, Type type) {
    return source.OfType<IMyObject>().Any(x => x.DataType.Equals(type));
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-24
    • 2023-03-26
    • 2016-11-11
    • 1970-01-01
    • 2019-06-04
    • 2011-08-23
    • 1970-01-01
    相关资源
    最近更新 更多