0

这就是我想在 C# 中做的事情(在class Helper- 没有泛型参数的情况下),

List<AbstractClass<dynamic>> data;

public void Add<T>(AbstractClass<T> thing)
{
    this.data.Add((AbstractClass<dynamic>) thing);
}

这个助手类将接受并使用AbstractClass<>对象并返回AbstractClass<>特定的泛型类型。AbstractClass<T>包含许多返回T/接收的函数,Tpublic T Invoke(). 对于 Helper 类T不能事先知道。该Add<T>(.. thing)函数不在 type 类中T。要在 Helper 类的函数中像这样使用,

foreach(var c in data.Where(x => ...))
{
    // public T Invoke() { ... } function within AbstractClass<T>
    var b = c.Invoke(); 
    // logic
}

这也失败了,

List<AbstractClass<object>> data;

public void Add<T>(AbstractClass<T> thing)
{
    this.data.Add((AbstractClass<object>) thing);
}

现在我想我可以拥有,

List<dynamic> data; // or List<object> data;

public void Add<T>(AbstractClass<T> thing)
{
    this.data.Add(thing);
}

但我想要 List 命名数据只有类型元素的约束

ConcreteClass : AbstractClass<OtherClass>

所以我们会知道有一个public T Invoke()函数,但我们不知道它返回什么。这有助于避免错误拼写 Invocke 和只在运行时知道的错误。

我想避免dynamic每次调用返回泛型类型 T 的函数

4

2 回答 2

1

要做你想做的事,你需要使用逆变接口

public class Program
{
    static void Main()
    {
        var m = new Helper();
        m.Add(new ConcreteClass());

        m.Process();
    }

    class Helper
    {
        List<IAbstractClass<OtherClassBase>> data = new List<IAbstractClass<OtherClassBase>>();

        public void Add(IAbstractClass<OtherClassBase> thing)
        {
            this.data.Add(thing);
        }

        public void Process()
        {
            foreach(var c in data.Where(x => x.ShouldBeProcessed()))
            {
                var b = c.Invoke();
                Console.WriteLine(b.Question);
                var castData = b as OtherClass;
                if (castData != null)
                    Console.WriteLine(castData.Answer);
            }
        }
    }

    public interface IAbstractClass<out T>
    {
        bool ShouldBeProcessed();
        T Invoke();
    }

    abstract class AbstractClass<T> : IAbstractClass<T>
    {
        public bool ShouldBeProcessed()
        {
            return true;
        }

        public abstract T Invoke();
    }

    class ConcreteClass : AbstractClass<OtherClass>
    {
        public override OtherClass Invoke()
        {
            return new OtherClass();
        }
    }


    class OtherClassBase
    {
        public string Question { get { return "What is the answer to life, universe, and everything?"; } }
    }

    class OtherClass : OtherClassBase
    {
        public int Answer { get { return 42; } }
    }
}

您不需要告诉Add您传递的是哪种类,重要的是它从指定的类型派生。你可以这样做public void Add(IAbstractClass<object> thing),每个类都可以工作,但Invoke()只会在 foreach 循环内返回对象。

您需要弄清楚要Invoke()返回的派生类最多的类是什么,这就是您在列表中设置的类型。

于 2013-08-02T16:28:59.410 回答
0

也许这对你有用:

public class Program
{
    static void Main()
    {
        var m1 = new Helper<OtherClass>();
        m1.Add(new ConcreteClass());
        var m2 = new Helper<int>();
        m2.Add(new ConcreteClass2());
    }
    class Helper<T>
    {
        List<AbstractClass<T>> data = new List<AbstractClass<T>>();

        public void Add<T1>(T1 thing) where T1 : AbstractClass<T>
        {
            this.data.Add(thing);
        }
    }
    class AbstractClass<T> { }
    class OtherClass { }
    class ConcreteClass : AbstractClass<OtherClass> { }
    class ConcreteClass2 : AbstractClass<int> { }
}
于 2013-08-02T16:16:01.427 回答