C#如何确定泛型类型

6
我有几个模板化的对象,它们都实现了相同的接口:
例如:
MyObject<datatype1> obj1;
MyObject<datatype2> obj2;
MyObject<datatype3> obj3;

我想把这些对象存储在一个列表中……我认为可以这样做:
private List<MyObject<object>> _myList;

我想创建一个函数,它接受1个参数(数据类型),以查看是否存在使用该数据类型的对象在我的列表中... 不知道该如何处理。 伪代码如下: ``` def check_datatype(datatype): for obj in my_list: if type(obj) == datatype: return True return False ```
public bool Exist(DataType T)
{
   return (does _myList contain a MyObject<T>?);
}

一些澄清...
我的接口是IMyObject ,我的对象是MyObject 。我有一个新的类MyObjectManager,我需要在其中存储一个MyObject 列表。我需要一个函数来检查该列表中是否存在MyObject 。类型T是使用T4自动生成的数据类型...从我的实体数据模型生成的POCO类。

如果它包含一个 MyObject<U>,而且 U 继承了 T,会怎样呢? - SLaks
我的U是使用T4和EF POCO类自动生成的。 - Chris Klepeis
类之间会继承吗? - SLaks
不,它们默认情况下不继承任何东西。 - Chris Klepeis
3个回答

6

您可以创建一个通用函数:

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<MyObject<object>> 无法 包含 MyObject<SomeType>
您需要将列表更改为 List<object>,或使 MyObject 实现或继承一个非泛型类型,并使列表包含该类型。


我的存储列表的类不会有通用类型,但是 MyObject<T> 中的 T 在编译时已知,并且这些对象的命名空间在此类中被引用。当我尝试使用您的第一个示例时,它会显示“类型 T 必须是引用类型才能用作参数”。我希望 T 是一种通用类型,以便我可以传递任何数据类型,无论是 int、string 等。 - Chris Klepeis
你需要添加一个 where T : class 约束,以匹配 MyObject 中的约束。 - SLaks

1

扩展方法怎么样?

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<T>的对象,那么我建议您采用SLaks的答案中提到的方法:
public static bool Exist<T>(this IEnumerable source) {
    return source.OfType<MyObject<T>>().Any();
}

此外,SLaks是正确的,你确实不能有一个List<MyObject<object>>,里面装满了除了MyObject<object>或某个派生类之外的任何对象(MyObject<datatype1>不是MyObject<object>派生出来的——泛型不是这样工作的)。

我可能会建议另一种方法来解决整个“你无法使用System.Type对象获取泛型类的类型而不使用反射”的问题:让你的MyObject<T>实现一个非泛型接口,像这样:

public interface IMyObject {
    Type DataType { get; }
}

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

那么你的列表可以是一个List<IMyObject>(非泛型接口),你的Exist方法可能如下所示:

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

0

由于它们都实现了相同的接口,为什么不添加一个名为类名(或其他名称)的属性到您的接口中,而不是将它们转换为对象并调用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 <T>。 - Chris Klepeis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接