是否有办法定义一种 "通用 "的func作为linq订单选择器来使用

问题描述 投票:0回答:2

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

// 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 "不能将匿名方法块转换为委托类型'委托类型',因为块中的一些返回类型不能隐式转换为委托返回类型",但是否可以定义一种类似于.NET的通用声明?

Func<MyNode, T> currentSort = sortByAge; // <-- Fails Compiler error CS1662

还是有其他的方法来处理?

c# func
2个回答
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;

0
投票

你的所有类型都实现了 IComparable. 作为 Func 是反变量,你可以分配任何返回该接口实例的委托。

所以这就可以了。

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

在这里阅读关于反变量的内容: https:/docs.microsoft.comde-dedotnetcsharpprogramming-guideconceptscovariance-contravarianceusing-variance-for-func-and-action-generic-delegates(反变量)


-2
投票

我只想用lambdas

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

小提琴


-2
投票

你可以用 IComparable.

https:/dotnetfiddle.net23R97J。

    Func<MyNode, IComparable> sortByName = x => x.Name;
    Func<MyNode, IComparable> sortByAge = x => x.Age;
    Func<MyNode, IComparable> sortById = x => x.Id;
    var currentSort = sortByAge;

EDIT: 就像其他人已经提到的那样,最好使用 IComparable 而不是 object,我之前的建议。

© www.soinside.com 2019 - 2024. All rights reserved.