有没有一种方法可以定义一种用作“ linq”顺序选择器的“通用”函数

时间:2020-05-13 16:16:13

标签: c# func

我有一个简单的对象列表,我想应用不同的过滤器和顺序选择器。过滤器没关系,但是对于顺序来说,我不知道如何定义“通用”选择器。

// The selector is always a bool
Func<MyNode, bool> isChild = x => x.Age < 18;
Func<MyNode, bool> isAdult = x => x.Age >= 18;

// So it's always ok to use
Func<MyNode, bool> isAgeOk = isAdult;

// The sort field can be different type (int, string, ...)
Func<MyNode, string> sortByName = x => x.Name;
Func<MyNode, int> sortByAge = x => x.Age;
Func<MyNode, int> sortById = x => x.Id;

// --------------> Is there a way to use a kind of generic declaration Func<MyNode, T> ?
Func<MyNode, int> currentSort = sortByAge;
// With this declaration, i can't use : Func<MyNode, int> currentSort = sortByName

List<MyNode> LstNodes = new List<MyNode>();
// ...Stuff to get nodes

// If I have this kind of linq, it's ok, but current sort is Fixed (Func<MyNode, int> in this example)
var result = LstNodes.Where(isAgeOk).Distinct().OrderBy(currentSort).ToList();

简单的类定义是

public class MyNode
{   
  public int Id  { get; set; }
  public string Name  { get; set; }
  public int Age { get; set; }          
}

我知道进一步的声明由于编译器错误CS1662“无法将匿名方法块转换为委托类型'委托类型'而失败,因为该块中的某些返回类型不能隐式转换为委托返回类型” 但是可以定义一种类似于:

的通用声明
Func<MyNode, T> currentSort = sortByAge; // <-- Fails Compiler error CS1662

还是有其他处理方式?

4 个答案:

答案 0 :(得分:1)

正如HimBromBeere所说,最好的方法是使用IComparable类型

代码。

        Func<PersonTest, IComparable> sortByName = x => x.Name;
        Func<PersonTest, IComparable> sortByAge = x => x.Age;
        Func<PersonTest, IComparable> sortByLastName = x => x.LastName;

        // --------------> Is there a way to use a kind of generic declaration Func<MyNode, T> ?
        Func<PersonTest, IComparable> currentSort = sortByName;

答案 1 :(得分:0)

您所有的类型都实现IComparable。由于Func是反变量,因此您可以分配任何返回该接口某些实例的委托。

这可行:

Func<MyNode, IComparable> myDelegate = myFunctionReturningString;
Func<MyNode, IComparable> myDelegate = myFunctionReturningInt;
Func<MyNode, IComparable> myDelegate = myFunctionReturningBool;

在此处了解有关反方差的信息:https://docs.microsoft.com/de-de/dotnet/csharp/programming-guide/concepts/covariance-contravariance/using-variance-for-func-and-action-generic-delegates

答案 2 :(得分:-2)

我只会使用lambda

var list = new List<MyNode>() {
new MyNode(){Id = 1, Name = "name1", Age = 1},
new MyNode(){Id = 2, Name = "name2", Age = 2},
new MyNode(){Id = 3, Name = "name3", Age = 3},
new MyNode(){Id = 4, Name = "name4", Age = 4},
new MyNode(){Id = 5, Name = "name5", Age = 5},
new MyNode(){Id = 6, Name = "name6", Age = 6},
new MyNode(){Id = 7, Name = "name7", Age = 7},
new MyNode(){Id = 8, Name = "name8", Age = 8},
        };

        var result = list.Where(n => n.Age >= 3).OrderBy(n => n.Age).ToList();

Fiddle

答案 3 :(得分:-2)

您可以使用Rec.Resolve

Line Graph for rainfall per month

IComparable

编辑:就像已经提到的其他人一样,最好使用 Func<MyNode, IComparable> sortByName = x => x.Name; Func<MyNode, IComparable> sortByAge = x => x.Age; Func<MyNode, IComparable> sortById = x => x.Id; var currentSort = sortByAge; 代替我之前建议的IComparable