0

我有一个像这样的通用类:

public class Foo<T>
{
    public string SomeMethod();
    ...
}

我希望存储对这种类型的不同通用实例的引用列表。例如

List<Foo<object>> foos = new List<Foo<object>>();

foos.Add(new Foo<string>());
foos.Add(new Foo<int>());
foos.Add(new Foo<Person>());

// Then do some processing like ...
foreach (var Foo<object> in foos)
{
     Console.WriteLine(foo.SomeMethod());
}

etc...

foos.Add 上的编译器错误说:

"Cannot convert from 'Foo<string>' to 'Foo<object>'

如何存储类型不同的泛型类型实例列表?

我不想只存储对象列表(ArrayList、List、List 等)并且必须使用反射来访问它们的成员!

4

2 回答 2

6

TinFoo<T>不需要DoSomething()。_ DoSomething()因此,您可以通过为该接口创建一个接口并将对象存储在该接口中来轻松解决该问题List<>

public interface ISomethingDoer {
    void DoSomething();
}

public class Foo<T> : ISomethingDoer {
    public void DoSomething() { }
}

和 -

List<ISomethingDoer> foos = new List<ISomethingDoer>();

foos.Add(new Foo<string>());
foos.Add(new Foo<int>());
foos.Add(new Foo<Person>());

// Then do some processing like ...
foreach (var foo in foos)
{
     Console.WriteLine(foo.DoSomething());
}
于 2013-11-10T12:35:08.197 回答
2

您想创建一个新接口,并将您的 SomeMethod() 放入其中,并让您的泛型实现它。这是最简单的解决方案。这就是它们存在的原因。

如果您的 SomeMethod 依赖于 T,那么您需要研究接口协变和逆变。

class Program
{
    public interface IFoo
    {
        void DoSomething();
    }

    public interface IGenericFoo<out T> : IFoo
    {
        T GetDefault();
    }


    public class Foo<T> : IGenericFoo<T>
    {
        public T GetDefault()
        {
            return default(T);
        }

        public void DoSomething()
        {
            Console.WriteLine("Meep!");
        }
    }


    private static void Main()
    {

        var fooCollection = new List<IFoo>
        {
            new Foo<string>(), 
            new Foo<StringBuilder>(),
            new Foo<int>()

        };
        foreach (var instance in fooCollection)
            instance.DoSomething();

        // Covariance example
        var fooCollectionGenericI = new List<IGenericFoo<object>>
        {
            new Foo<string>(), 
            new Foo<StringBuilder>(),
            // new Foo<int>() not possible since covariance is not supported on structs :( 
        };

        foreach (var instance in fooCollectionGenericI)
        {
            var wxp = instance.GetDefault();
            Console.WriteLine(wxp == null ? "NULL" : wxp.ToString());
        }

        Console.ReadLine();
    }
}

这种协方差在某些情况下可能非常有用。

于 2013-11-10T12:34:05.593 回答