【问题标题】:Using generic types within a foreach loop在 foreach 循环中使用泛型类型
【发布时间】:2020-05-28 13:22:37
【问题描述】:

我真的不知道如何将泛型类型与 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 属性)。

【问题讨论】:

  • foreach 循环中,您希望v 属于哪种类型?换句话说,Convert.UInt64 接受什么?
  • 另外,“ANY TYPE”意味着你回退到一个通用对象。在 bool 和 bool[] 之间没有完全相同的东西。你最好至少有几个方法——一个用于数组,一个不用于。数组。
  • TBH,如果你有特定类型的行为,泛型可能不是这里的正确选择。
  • 看起来您需要不止一种泛型类型,因为T : IEnumerable&lt;T&gt; 没有多大意义。可能是Parameter&lt;T, U&gt; : IParameter&lt;T, U&gt; where T : IEnumerable&lt;U&gt; 之类的东西?请注意,bool[] 与该约束不匹配,因为它是 IEnumerable&lt;bool&gt; 而不是 IEnumreable&lt;bool[]&gt; 如果您需要处理单个项目和集合,那么您应该将它们分开,因为您无法以通用方式处理它们(除非您只需将单个项目强制放入集合中)。
  • 恕我直言; public IEnumerable&lt;T&gt; Value { get ... set ... }

标签: c# generics ienumerable


【解决方案1】:

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

public class Parameter&lt;T&gt; : IParameter&lt;T&gt; where T : IEnumerable&lt;T&gt;

暗示任何类型的 T 都是相同类型的可枚举,例如,bool[] 类型的 T 应该是 IEnumerable&lt;bool[]&gt;,这显然是不正确的。

编译它的一种方法是:

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

【讨论】:

  • 谢谢,无论如何我可以在“Parameter”中有一个“参数”。 IE。我们可以以某种方式将 TEnumerable 和 TType 结合起来,这样我就不需要使用两者来声明每个参数,例如。
  • 添加了更新。我真的不知道你想要达到什么目的,所以我只是在给定原始代码的情况下尽力而为。
  • 哦,但这对数组和非数组类型都有效吗?
  • 它适用于任何事情。类型不受约束。但Value 属性将始终是T 类型的可枚举
  • 那么,您是说我需要选项 1(支持数组和非数组类型)或该类的 2 个单独实现(一个用于数组,一个用于非数组类型)?
猜你喜欢
  • 1970-01-01
  • 2021-09-21
  • 2010-12-25
  • 2020-05-30
  • 1970-01-01
  • 1970-01-01
  • 2013-04-05
  • 2022-08-14
  • 1970-01-01
相关资源
最近更新 更多