Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#在抽象类中转换泛型T<;T>;动态_C#_Generics_Dynamic - Fatal编程技术网

C#在抽象类中转换泛型T<;T>;动态

C#在抽象类中转换泛型T<;T>;动态,c#,generics,dynamic,C#,Generics,Dynamic,这就是我在C#中要做的事情(在类帮助程序中-没有泛型参数) 这也失败了, List<AbstractClass<object>> data; public void Add<T>(AbstractClass<T> thing) { this.data.Add((AbstractClass<object>) thing); } 列表数据; 公共空添加(抽象类) { this.data.Add((AbstractClass)th

这就是我在C#中要做的事情(在
类帮助程序中
-没有泛型参数)

这也失败了,

List<AbstractClass<object>> data;

public void Add<T>(AbstractClass<T> thing)
{
    this.data.Add((AbstractClass<object>) thing);
}
列表数据;
公共空添加(抽象类)
{
this.data.Add((AbstractClass)thing);
}
现在我想我可以

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

public void Add<T>(AbstractClass<T> thing)
{
    this.data.Add(thing);
}
列出数据;//或列出数据;
公共空添加(抽象类)
{
这个。数据。添加(东西);
}
但我需要一个约束,即列表命名数据只包含以下类型的元素

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


我希望避免每次调用返回泛型类型T的函数时都强制转换为
动态
,也许这对您有用:

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> { }
}
公共类程序
{
静态void Main()
{
var m1=新助手();
m1.添加(新的ConcreteClass());
var m2=新助手();
m2.增加(新混凝土类别2());
}
类助手
{
列表数据=新列表();
公共void Add(T1 thing),其中T1:AbstractClass
{
这个。数据。添加(东西);
}
}
类抽象类{}
类其他类{}
类ConcreteClass:AbstractClass{}
类ConcreteClass2:AbstractClass{}
}

要想做你想做的事,你需要使用

公共类程序
{
静态void Main()
{
var m=新助手();
m、 添加(新的ConcreteClass());
m、 过程();
}
类助手
{
列表数据=新列表();
公共作废添加(IAbstractClass对象)
{
这个。数据。添加(东西);
}
公共程序()
{
foreach(data.Where(x=>x.shouldbeeprocessed())中的变量c)
{
var b=c.Invoke();
控制台。写线(b.问题);
var castData=b作为其他类;
if(castData!=null)
Console.WriteLine(castData.Answer);
}
}
}
公共接口IAbstractClass
{
bool应该被处理();
T Invoke();
}
抽象类AbstractClass:IAbstractClass
{
公共bool应该被处理()
{
返回true;
}
公共摘要T Invoke();
}
类ConcreteClass:AbstractClass
{
公共重写其他类调用()
{
返回新的OtherClass();
}
}
类OtherClassBase
{
公共字符串问题{get{return“生命、宇宙和一切的答案是什么?”;}
}
类OtherClass:OtherClassBase
{
公共int应答{get{return 42;}}
}
}
您不需要告诉
Add
您要传递的是什么类型的类,重要的是它派生自指定的类型。您可以执行
public void Add(IAbstractClass事情)
并且每个类都可以工作,但是
Invoke()
只会返回foreach循环中的对象


您需要找出您希望
Invoke()
返回的最派生的类是什么,这就是您在列表中设置为类型的类。

为什么不将数据声明为
列表数据
?包含
列表数据的类不是T类型。
Add(…thing)
函数必须处理添加许多不同的具体对象,这些对象扩展了AbstractClass,而不知道T是什么。我希望这有点道理。这就是
类帮助程序{…列出数据;public void Add(…数据){…}..}
除了单个实例帮助程序需要能够接受扩展
抽象类、AbtrasctClass、。。。AbtrasctClass
ConcreteClass : AbstractClass<OtherClass>
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> { }
}
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; } }
    }
}