【问题标题】:Possible to create a single multi-type collection of multi-type lambda functions in C# 4.0?可以在 C# 4.0 中创建多类型 lambda 函数的单个多类型集合吗?
【发布时间】:2011-08-18 00:32:51
【问题描述】:

例如:

Dictionary<string, Func<T1, T2, bool>> comparisons;
    comparisons.add("<", (x, y) => x < y);
    comparisons.add("==", (x, y) => x == y);
    comparisons.add(">", (x, y) => x > y);

在这一点上,我对 C# lambda 和多类型泛型容器的了解还不够,无法正确地将它们组合在一起。这甚至可能吗?

【问题讨论】:

  • 查看Predicate 代表。
  • 你真的想要泛型类型T1T2吗?你永远无法比较那些......
  • @jeroenh 是的,我想让它尽可能通用。部分吸引力在于使这个块如此简洁。 Guffa 的答案看起来像是通过用 IComparable 替换 T1 和 T2 并使用 CompareTo() 方法来解决这个问题。

标签: c# .net collections dictionary lambda


【解决方案1】:

是的,拥有这样的东西是完全有效的:

Dictionary<string, Func<int, int, bool>> comparisons = new Dictionary<string, Func<int, int, bool>>();

comparisons.Add("<", (x, y) => x < y);
comparisons.Add("==", (x, y) => x == y);
comparisons.Add(">", (x, y) => x > y);

但在您的示例中,您需要使用Func&lt;int, int, bool&gt;,因为您采用两个参数并返回一个布尔值。

你也可以把它放在一个通用的实现中,但是你需要某种方式来限制它,这样任何东西都必须实现 运算符。

【讨论】:

  • 嗯,我不会只传递整数。它们总是成对的,但它可能是整数对、字符串、布尔值、小数等。关于如何保持它的通用性,或者只是捕获可能引发的可比性异常的任何想法?
  • 只要将泛型约束为值类型,就可以将类型设为泛型。这应该是有效的:Compare&lt;T&gt; where T: ValueType
【解决方案2】:

泛型类型必须在编译时知道,所以你不能做动态委托。如果指定数据类型,则可以创建委托字典:

Dictionary<string, Func<int, int, bool>> comparisons;
comparisons.add("<", (x, y) => x < y);
comparisons.add("==", (x, y) => x == y);
comparisons.add(">", (x, y) => x > y);

你可以使用IComparable接口来允许不同的类型,但是你只能使用它的CompareTo方法来实现操作符:

Dictionary<string, Func<IComparable, IComparable, bool>> comparisons;
comparisons.add("<", (x, y) => x.CompareTo(y) < 0);
comparisons.add("==", (x, y) => x.CompareTo(y) == 0);
comparisons.add(">", (x, y) => x.CompareTo(y) > 0);

这当然对所使用的数据的限制较少,例如,您可以将 stringDateTime 值提供给操作员委托,并且它编译得很好。直到你运行它才会失败。

【讨论】:

    【解决方案3】:
    Func<int, int, bool> t = null;
    
    var comparisons = new Dictionary<string, Func<int, int, bool>>
                                  {
                                      {"<", (x, y) => x < y},
                                      {"==", (x, y) => x == y},
                                      {">", (x, y) => x > y}
                                  };
    
    t = comparisons["<"];
     bool result = t(1,2);
    

    【讨论】:

    • 这是不正确的。您绝对可以在访问该方法后立即调用它:comparisons["&lt;"](1,2) 是有效(且工作)代码。
    • 我认为您不需要临时代表。直接从字典中调用它就可以了。
    【解决方案4】:

    是的,可以这样做,但只有在所有泛型类型参数都被赋予具体类型时才能这样做。例如,这有效:

    Dictionary<string, Func<int, int, bool>> comparisons = new Dictionary<string, Func<int, int, bool>>();
    

    没有办法做到这一点(在伪 C++ 语法中):

    Dictionary<string, Func<?, ?, bool>> comparisons = new Dictionary<string, Func<?, ?, bool>>();
    

    【讨论】:

    • +1 用于 C++ 参考:D。我一直希望 .Net 泛型中的一些更高级的模板功能:(
    【解决方案5】:

    我看不出拥有 T1 和 T2 的意义;如果有不同的类型,你通常无法比较吗?

    如果你想保持通用,你可以这样做(我将比较字典存储在一个字段中):

    class MyClass<T> where T:IComparable<T> 
    {
        private Dictionary<string, Func<T, T, bool>> comparisons
            = new Dictionary<string, Func<T, T, bool>>
                  {
                      {"<", (x, y) => x.CompareTo(y) < 0},
                      {"==", (x, y) => x.Equals(y)},
                      {">", (x, y) => x.CompareTo(y) > 0}
                  };
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-11
      相关资源
      最近更新 更多