【问题标题】:Looping over List of different generic types in c#在c#中循环不同泛型类型的列表
【发布时间】:2020-05-30 10:16:17
【问题描述】:

我有一个由不同的泛型类型组成的列表,例如:

public abstract class BaseClass {}

public class BaseChild<T> : BaseClass {
   public SomeOtherClass<T> data;
}

List<BaseClass> items;
items.Add(new BaseChild<int>());
items.Add(new BaseChild<bool>());
items.Add(new BaseChild<double>());

我现在想遍历这个列表并将SomeOtherClass 类型的每个项目的data 属性传递给另一个泛型类中相同类型的字段。像这样的

public class GenClass<T> {
   public SomeOtherClass<T> assignHere;
}

for(int i=0;i<=items.Count;i++){
   // this does not work. It is unable to get data since it is not
   // defined in BaseClass and the List is of type BaseClass
   items[i].data;
   // somehow assign to assignHere field in GenClass<T> since I don't know type
}

我有两个问题:

  1. 我如何访问数据字段,因为它只定义在继承者而不是父类上?我循环的列表是 BaseClass 类型而不是 BaseChild&lt;T&gt;

  2. 如果我不知道循环时的类型,如何将数据分配给GenClass&lt;T&gt; 中的assignHere 字段?

编辑: SomeOtherClass&lt;T&gt;的代码

public class SomeOtherClass<T>{
   public T Value;
   public GameEvent<T> event
}

public GameEvent<T>:UnityEvent<T>{
   public void Raise(T value){
      //does something
   }

}

编辑#2:这是我尝试过并且有效的一种实现方式。这样更好吗?

public abstract class BaseButton
    {
        public string displayText;

        public abstract void TriggerButton();
    }

public class IntButton : BaseButton
{
    public IntEvent triggerEvent;
    public int Value;

    public override void TriggerButton()
    {
        triggerEvent.Raise(Value);
    }
}

public class IntEvent : BaseGameEvent<int>{}

public abstract class BaseGameEvent<T>{
    public void Raise(T value){
        // do something
    }
}

谢谢!

【问题讨论】:

  • 如果您需要使用子类型,基本类型列表的优势是什么?是否保证列表中只有孩子?
  • 可以添加SomeOtherClass类的代码吗?
  • 泛型是一个编译时特性。当您将实际类型放在 runtime 时,编译器应该如何推断正确的类型?这是编译器没有机会知道的,例如索引 2 处的项目是 BaseChild&lt;double&gt; 类型。因此,即使您可以通过任何方式访问 data,您也无能为力。
  • 数据从何而来?你能澄清一下数据流吗?通常你会尝试创建一个没有输入参数的方法,但从内部触发事件

标签: c# generics arraylist


【解决方案1】:

带反射:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");

        List<BaseClass> items = new List<BaseClass>();
        items.Add(new BaseChild<int>());
        items.Add(new BaseChild<bool>());
        items.Add(new BaseChild<double>());

        for (int i = 0; i <= items.Count; i++)
        {
            var generated = Convert(items[i]);
            if (generated is GenClass<int> genInt)
            {
                Console.WriteLine(genInt?.assignHere?.Value);
            }
            else if (generated is GenClass<bool> genBool)
            {
                Console.WriteLine(genBool?.assignHere?.Value);
            }
        }
    }

    static object Convert(BaseClass item)
    {
        var type = item.GetType().GenericTypeArguments[0];
        var method = typeof(Program).GetMethod("GenericConvert", BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(type);
        return method.Invoke(null, new[] { item });
    }

    static GenClass<T> GenericConvert<T>(BaseChild<T> from)
    {
        return new GenClass<T> { assignHere = from.data };
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-01
    • 2010-12-06
    相关资源
    最近更新 更多