在C#中将通用对象添加到通用列表

时间:2023-01-17 14:20:55

I have class where the relevant part looks like

我上课的相关部分看起来像

class C {
    void Method<T>(SomeClass<T> obj) {
        list.Add(obj);
    }
    List<?> list = new List<?>();
}

How should I define the list so that the class compiles?

我应该如何定义列表以便类编译?

I want a list of type List<SomeClass<?>>, that is a list of objects of SomeClass where each object can have any type parameter. The Java ? construct allows this; what is the C# equivalent? If no such thing exists, is there a suitable workaround? (A List<object> would do but is terribly ugly.)

我想要一个List >类型的列表,它是SomeClass的对象列表,其中每个对象可以有任何类型参数。 Java?构造允许这个;什么是C#等价物?如果不存在这样的事情,是否有合适的解决方法? (列表 会做但非常难看。)

5 个解决方案

#1


I don't think you can do this in C#... you would have to add the type parameter to the class:

我认为你不能在C#中做到这一点......你必须在类中添加type参数:

class C<T> {
    void Method(SomeClass<T> obj) {
        list.Add(obj);
    }
    List<SomeClass<T>> list = new List<SomeClass<T>>();
}

The other option would be to use an interface:

另一种选择是使用接口:

class C {

    void Method<T>(T obj)
         where T : ISomeClass {
        list.Add(obj);
    }
    List<ISomeClass> list = new List<ISomeClass>();
}

#2


To do what you want, you have two options.

要做你想做的事,你有两个选择。

You can use List<object>, and handle objects. This will not be typesafe, and will have boxing/unboxing issues for value types, but it will work.

您可以使用List ,并处理对象。这不是类型安全的,并且会为值类型设置装箱/拆箱问题,但它会起作用。

Your other option is to use a generic constraint to limit to a base class or interface, and use a List<Interface>.

您的另一个选择是使用通用约束来限制基类或接口,并使用List

#3


Unfortunately, there is no direct equivalent in C# 3.0 as generics are invariant. You'll be able to do something like this in a graceful manner using C# 4.0 safe co/contra-variance feature. To workaround it, you could inherit SomeClass<T> from a nongeneric base and create a List<BaseClass> instead. If each instance of the class should hold only one type, you could make the class itself generic and set the type parameter there.

不幸的是,在C#3.0中没有直接的等价物,因为泛型是不变的。您将能够使用C#4.0安全协同/反向差异功能以优雅的方式执行此类操作。要解决此问题,您可以从非泛型基础继承SomeClass 并创建List 。如果类的每个实例只应包含一个类型,则可以使类本身具有通用性并在那里设置类型参数。

#4


I don't know anything about Java's ? construct, but I think the following most closely preserves your existing syntax while also matching your description.

我对Java没有任何了解?构造,但我认为以下最接近保留现有语法,同时也符合您的描述。

    class SomeClass<T>
    {
    }

    class C
    {
        void Add<T>(SomeClass<T> item)
        {
            Type type = typeof(SomeClass<T>);
            if (!list.ContainsKey(type))
                list[type] = new List<SomeClass<T>>();
            var l = (List<SomeClass<T>>)list[type];
            l.Add(item);
        }

        public void Method<T>(SomeClass<T> obj)
        {
            Add(obj);
        }
        readonly Dictionary<Type, object> list = new Dictionary<Type, object>();
    }

test it with the following:

用以下方法测试它:

    class Program
    {
        static void Main(string[] args)
        {
            var c = new C();
            var sc1 = new SomeClass<int>();
            var sc2 = new SomeClass<String>();
            c.Method(sc1);
            c.Method(sc2);
            c.Method(sc1);
            c.Method(sc2);
        }
    }

#5


Personally, I would do this where possible; move the generic parameter from the method, to the class.

就个人而言,我会尽可能地这样做;将泛型参数从方法移动到类。

class C<T> {
    void Method(SomeClass<T> obj) {
        list.Add(obj);
    }
    List<?> list = new List<?>();
}

If your generic list is a member, it stands to reason that the class should be constructed with this in mind. It is hard for us to suggest the best pattern without more usage context for the class.

如果你的通用列表是一个成员,那么就应该考虑到这个类的构造。如果没有更多的使用环境,我们很难建议最好的模式。

#1


I don't think you can do this in C#... you would have to add the type parameter to the class:

我认为你不能在C#中做到这一点......你必须在类中添加type参数:

class C<T> {
    void Method(SomeClass<T> obj) {
        list.Add(obj);
    }
    List<SomeClass<T>> list = new List<SomeClass<T>>();
}

The other option would be to use an interface:

另一种选择是使用接口:

class C {

    void Method<T>(T obj)
         where T : ISomeClass {
        list.Add(obj);
    }
    List<ISomeClass> list = new List<ISomeClass>();
}

#2


To do what you want, you have two options.

要做你想做的事,你有两个选择。

You can use List<object>, and handle objects. This will not be typesafe, and will have boxing/unboxing issues for value types, but it will work.

您可以使用List ,并处理对象。这不是类型安全的,并且会为值类型设置装箱/拆箱问题,但它会起作用。

Your other option is to use a generic constraint to limit to a base class or interface, and use a List<Interface>.

您的另一个选择是使用通用约束来限制基类或接口,并使用List

#3


Unfortunately, there is no direct equivalent in C# 3.0 as generics are invariant. You'll be able to do something like this in a graceful manner using C# 4.0 safe co/contra-variance feature. To workaround it, you could inherit SomeClass<T> from a nongeneric base and create a List<BaseClass> instead. If each instance of the class should hold only one type, you could make the class itself generic and set the type parameter there.

不幸的是,在C#3.0中没有直接的等价物,因为泛型是不变的。您将能够使用C#4.0安全协同/反向差异功能以优雅的方式执行此类操作。要解决此问题,您可以从非泛型基础继承SomeClass 并创建List 。如果类的每个实例只应包含一个类型,则可以使类本身具有通用性并在那里设置类型参数。

#4


I don't know anything about Java's ? construct, but I think the following most closely preserves your existing syntax while also matching your description.

我对Java没有任何了解?构造,但我认为以下最接近保留现有语法,同时也符合您的描述。

    class SomeClass<T>
    {
    }

    class C
    {
        void Add<T>(SomeClass<T> item)
        {
            Type type = typeof(SomeClass<T>);
            if (!list.ContainsKey(type))
                list[type] = new List<SomeClass<T>>();
            var l = (List<SomeClass<T>>)list[type];
            l.Add(item);
        }

        public void Method<T>(SomeClass<T> obj)
        {
            Add(obj);
        }
        readonly Dictionary<Type, object> list = new Dictionary<Type, object>();
    }

test it with the following:

用以下方法测试它:

    class Program
    {
        static void Main(string[] args)
        {
            var c = new C();
            var sc1 = new SomeClass<int>();
            var sc2 = new SomeClass<String>();
            c.Method(sc1);
            c.Method(sc2);
            c.Method(sc1);
            c.Method(sc2);
        }
    }

#5


Personally, I would do this where possible; move the generic parameter from the method, to the class.

就个人而言,我会尽可能地这样做;将泛型参数从方法移动到类。

class C<T> {
    void Method(SomeClass<T> obj) {
        list.Add(obj);
    }
    List<?> list = new List<?>();
}

If your generic list is a member, it stands to reason that the class should be constructed with this in mind. It is hard for us to suggest the best pattern without more usage context for the class.

如果你的通用列表是一个成员,那么就应该考虑到这个类的构造。如果没有更多的使用环境,我们很难建议最好的模式。