在foreach循环中使用泛型类型

时间:2020-05-28 13:22:37

标签: c# generics ienumerable

我真的无法弄清楚如何将泛型类型与IEnumerable一起使用,以便可以迭代给定泛型值包含的值。

请考虑以下类(请注意,此处的类仅出于示例目的):

public class Parameter<T> : IParameter<T> where T : IEnumerable<T>
{
  public List<UInt64> output = new List<UInt64>();

   private T _value;
   public T Value
   {
       get => ...;
       set
       {

           // I want to be able to apply special treat to the value
           // Value can be of any type: int, int[], bool, bool[]
           foreach (var v in value)
           {
               output.Add(Convert.UInt64(v) + 5);
           }

           ...

       }
   }
}

public interface IParameter<T> where T : IEnumerable<T>
{
   T Value { get; set; }
}

然后我有一个测试模块,该模块按照实例化一些参数,但是我什至不能在这里编译。我什至在下面尝试将bool []替换为IEnumerable,但编译器也不喜欢。

public class TestModule : ModuleBase, ITestModule
{
    public IParameter<bool[]> Test1 { get; set; } = new Parameter<bool[]>();
    public IParameter<uint[]> Test2 { get; set; } = new Parameter<uint[]>();
    ...
    public IParameter<int> Test3 { get; set; } = new Parameter<int>();
}

我确实考虑过对Parameter()类使用重载,但是我认为为每个受支持的类型创建一个类(考虑到它仅用于Value属性)是过大的。

1 个答案:

答案 0 :(得分:1)

您的问题是您的通用参数指定不正确。

public class Parameter<T> : IParameter<T> where T : IEnumerable<T>

暗示类型T出现的任何东西都是相同类型的枚举,例如,类型bool[]的T应该是IEnumerable<bool[]>,这显然是不正确的。

一种使其编译的方法是:

    public class Parameter<TEnumerable, TType> : IParameter<TEnumerable, TType> where TEnumerable : IEnumerable<TType>
    {
        public List<ulong> output = new List<ulong>();

        private TEnumerable _value;
        public TEnumerable Value
        {
            get => { return null; }
            set
            {

                // I want to be able to apply special treat to the value
                // Value can be of any type: int, int[], bool, bool[]
                foreach (Q v in value)
                {
                    output.Add(Convert.ToUInt64(v) + 5);
                }
            }
        }
    }

    public interface IParameter<TEnumerable, TType> where TEnumerable : IEnumerable<TType>
    {
        TEnumerable Value { get; set; }
    }

    public class TestModule
    {
        public IParameter<bool[], bool> Test1 { get; set; } = new Parameter<bool[], bool>();
        public IParameter<uint[], uint> Test2 { get; set; } = new Parameter<uint[], uint>();
        public IParameter<int[], int> Test3 { get; set; } = new Parameter<int[], int>();
    }

关于您的其他评论,不,您无法避免必须指定两种类型,因为IEnumerable并不是您编写代码的形式中的T。您在此处有2个单独的参数,因此,如果必须按照自己的方式进行操作,则必须使用2个通用参数。

一个更简单的解决方案是这样的,它或多或少地达到了相同的目的,尽管我真的不知道您的要求,所以可能满足或不满足(为清楚起见,省略了接口):

    public class Parameter<TType>
    {
        public List<ulong> output = new List<ulong>();

        private IEnumerable<TType> _value;
        public IEnumerable<TType> Value
        {
            get => { return null; }
            set
            {

                // I want to be able to apply special treat to the value
                // Value can be of any type: int, int[], bool, bool[]
                foreach (TType v in value)
                {
                    output.Add(Convert.ToUInt64(v) + 5);
                }
            }
        }
    }

    public class TestModule
    {
        public Parameter<bool> Test1 { get; set; } = new Parameter<bool>();
        public Parameter<uint> Test2 { get; set; } = new Parameter<uint>();
        public Parameter<int> Test3 { get; set; } = new Parameter<int>();
    }