繁体   English   中英

在不知道类型的情况下引用泛型类型的实例

[英]Referencing instances of Generic Type without knowing the Type

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

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上的编译器错误。添加呼叫说:

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

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

我不想只存储对象列表(ArrayList,List,List等),而不必使用反射来访问其成员!

TFoo<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());
}

您想要创建一个新接口,并将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();
    }
}

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM