【问题标题】:C# make a Dictionary of LambdasC# 制作 Lambda 字典
【发布时间】:2013-07-30 13:29:42
【问题描述】:

我在定义字典以快速访问 Lambda 表达式时遇到问题。

假设我们有一个像这样的知名类:

class Example
{
    public string Thing1;
    public DateTime Thing2;
    public int Thing3;
}

一个想做的事情是这样的:

var getters = new Dictionary<string, IDontKnowWhatGoesHere>();
getters.Add("Thing1", x => x.Thing1);
getters.Add("Thing3", x => x.Thing3);

这可能吗?

编辑:

这是我对这个对象的用例:

List<Example> array = new List<Example>();

// We actually get this variable set by the user
string sortField = "Thing2";

array.Sort(getters[sortField]);

非常感谢您的帮助。

【问题讨论】:

  • 您试图将Func&lt;Example, string&gt; 存储为字典中的值类型?这是你想要的吗?你想用这个做什么?
  • 所以你想存储表达式?
  • 你能说一下你需要这个吗?然后我们会写出更好的解决方案。
  • 为什么要使用字典?为什么没有List&lt;Example&gt;?然后你可以使用 linq 。无需限制您可以持有的数据量。
  • 嘿,我想快速访问 lambda 表达式。例如... IEnumerable a; a.OrderBy(getters["Thing3"])

标签: c# lambda expression-trees


【解决方案1】:

您有几个选择。如果像你的例子一样,你想要得到的东西都是相同的类型(即String),你可以这样做

var getters = new Dictionary<string, Func<Example, String>>();

但是,如果它们是不同的类型,则需要使用最低的公共子类,在大多数情况下为Object

var getters = new Dictionary<string, Func<Example, object>>();

请注意,您需要将返回值转换为您的预期类型。

【讨论】:

  • 按键,是的。按价值,不是真的:代表不实现IComparable,因此您需要编写自己的IComparer。如果这是您的意图,您可能会发现使用表达式更容易,例如 Dictionary&lt;string, Expression&lt;Func&lt;Example, string&gt;&gt; - 但这是一个全新的问题。
  • 很抱歉你弄错了,我想这样做: List a; a.OrderBy(getters["Thing1"]);我需要解决的问题是在不编写巨型开关盒的情况下制作动态 OrderBy。排序字段来自客户端
  • @AdrianSalazar 我没有注意到您的编辑。在这种情况下它会正常工作,即使使用Func&lt;Example, object&gt;
  • 谢谢我已经实现它并且它有效。不使用反射的轻量级动态排序...
【解决方案2】:

试试:

var getters = new Dictionary<string, Func<Example, object>>();
getters.Add("Thing1", x => x.Thing1);
getters.Add("Thing3", x => x.Thing3);

Func 委托的第一个泛型类型参数是输入的类型,第二个泛型类型参数是输出的类型(使用 object,因为您有不同的输出类型)。 更多关于FuncFunc&lt;T, TResult&gt; Delegate

【讨论】:

    【解决方案3】:
    var getters = new Dictionary<string, Expression<Func<Example, object>>>();
    

    但是,string Thing1 应该是公开的。

    【讨论】:

    • 在这种情况下可以正常工作吗? IEnumerable.OrderBy(getters["Thing1"])
    【解决方案4】:

    我真的认为你以错误的方式思考这个问题。为什么要使用字典?如果您的类定义正确,则只需使用List&lt;Example&gt;

    List<Example> dataList = new List<Example>();
    dataList.Add(new Example { Thing1 = "asdf", Thing2 = "qwert", Thing3 = 2 });
    

    那么你就可以在上面使用linq了。

    IEnumerable<Example> sortedByT3 = dataList.OrderBy(x => x.Thing3);
    
    sortedByT3.Last().Thing2 = "hjkl";
    

    您也可以使用Marc Gravell's answer提供的dynamic order by

    var sortedByString = dataList.AsQueryable().OrderBy("Thing2");
    

    不需要 lambda,只需直接访问数据即可。

    正如大家所说,您需要将成员公开。我建议您将其更改为以下内容:

    public class Example
    {
        public string Thing1 { get; set; }
        public string Thing2 { get; set; }
        public int Thing3 { get; set; }
    }
    

    【讨论】:

    • 是的,我明白你的意思,问题是我需要知道我想在第一次对哪个字段进行排序。所以我可以像我们古代程序员通常做的那样做一个大的开关盒。我可以忍受,但我想知道 DLR、TypeInference、Generics 和 Lambdas 是否可以给我另一种方式。
    • @AdrianSalazar,比如dynamic linqweblogs.asp.net/scottgu/archive/2008/01/07/…
    • 是的,你明白我的意思,但我根本没有连接到 SQL ......而且我不想在一天之内拯救世界并让它变得超级通用。如果它适用于这个特定的类,那就足够了。
    • @AdrianSalazar,好的,我明白你的意思了。我会再给你一个建议:stackoverflow.com/q/41244/1043380,我会保留这个答案以供将来参考。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多