是否可以在C#中创建具有自定义值或模板化值的谓词 我对C是比较新的,来自C++背景。我一直在寻找一个列表搜索和Find的用法

是否可以在C#中创建具有自定义值或模板化值的谓词 我对C是比较新的,来自C++背景。我一直在寻找一个列表搜索和Find的用法,c#,list,predicate,C#,List,Predicate,我试图定义一个函数,它接受一个参数,并从列表中返回一个条目。比如说 class Product { public string id; public string description; } public List<Product> products = new List<Product>(); // Add some items to the list 我尝试过使用谓词,但似乎无法找到任何方法将值输入到函数中,以对其执行布尔表达式检查。我理解如何编

我试图定义一个函数,它接受一个参数,并从列表中返回一个条目。比如说

class Product
{
    public string id;
    public string description;
}

public List<Product> products = new List<Product>();
// Add some items to the list
我尝试过使用谓词,但似乎无法找到任何方法将值输入到函数中,以对其执行布尔表达式检查。我理解如何编写谓词来查找列表中的特定项,而不是可以传入的动态项

理想情况下,我希望进一步对其进行模板化,以便谓词可以用于具有类似结构的任何项目列表

i、 e如果我们也有

class Employee
{
    public string id;
    public int age;
}

public List<Employee> employees = new List<Employee>();
// Add some items to the list
class员工
{
公共字符串id;
公共信息;
}
公共列表员工=新列表();
//将一些项目添加到列表中
如果使用同一个定义的谓词,但是在这个列表中使用完全不同的类型,那将非常酷。例如

// psudo
Predicate<T, string> predicate = return <T>.id == id;
//psudo
谓词=return.id==id;
它之所以能工作,是因为T的类型总是有一个名为
id

我希望这一切都有意义

我理解如何编写谓词来查找列表中的特定项,而不是可以传入的动态项

这就是lambda表达式的用武之地,它允许您创建一个代理类型的实例来捕获范围中的变量。例如:

公共谓词CreateProductPredicateForId(字符串id)
{
退货产品=>product.id==id;
}
现在,为了使其通用化,您需要有一个指定
Id
属性的接口。然后可以编写一个泛型方法。例如:

公共接口的可扩展性
{
字符串Id{get;}
}
...
公共谓词CreatePredicateForId(字符串id),其中T:IEntity
{
返回entity=>entity.Id==Id;
}
(注意:在整个过程中,我使用的是
Func
——但同样的逻辑适用于
谓词
——它们具有等效的签名,但现在您往往会看到前者多于后者;也就是说:
列表
使用后者)

泛型支持这一点,但通过方差规则;您必须声明表单的接口:

接口IHazId
{
int Id{get;}
}
class Foo:IHazId//您的类型也需要实现它!
{
公共int Id{get;set;}
}
然后你可以用一般的方式使用它:

void SomeCallingCode() { // get the predicate, however int id = 42; Func<IHazId, bool> predicate = obj => obj.Id == id; // use it SomeTypeSpecificMethod(predicate); } void SomeTypeSpecificMethod(Func<Foo, bool> predicate) => throw new NotImplementedException("not shown"); 但是,在现实中,这很少有用,因为在大多数情况下,您已经知道类型,并且只想执行以下操作:

int id = 42; SomeTypeSpecificMethod(x => x.Id == id); int id=42; SomeTypeSpecificMethod(x=>x.Id==Id); 还请注意,允许您将
Func
视为
Func
的差异规则仅适用于引用类型
SomeType
——也就是说:
class
,而不是
struct
,您可以使用LINQ

Product myProduct = products.Where(p => p.Id == id).FirstOrDefault();
您需要
使用System.Linq以使用它

Product GetProductByID(string id)
{
    foreach (Product p in products)
    {
        if (p.id == id)
        {
            return p;
        }
    }
}
这可以用

products.FirstOrDefault(p => p.Id == id)
你问题的第二部分可以通过继承很容易地解决,比如

public class ProductA
{
    public string Id { get; set; }
}

public class ProductB : ProductA
{
    
}

List<ProductA> a = new List<ProductA>();
List<ProductB> b = new List<ProductB>();

Func<ProductA, bool> findFunction = (p) => p.Id == id;

var p = a.FirstOrDefault(findFunction);
p = b.FirstOrDefault(findFunction);
公共类产品a
{
公共字符串Id{get;set;}
}
公共类ProductB:ProductA
{
}
列表a=新列表();
列表b=新列表();
Func findFunction=(p)=>p.Id==Id;
var p=a.FirstOrDefault(findFunction);
p=b.FirstOrDefault(findFunction);

虽然这适用于
产品
,但它并不能解决OP的要求,即对具有
id的不同类型使用单个谓词。@marcGravel:Whoops,yes-修复。
products.FirstOrDefault(p => p.Id == id)
public class ProductA
{
    public string Id { get; set; }
}

public class ProductB : ProductA
{
    
}

List<ProductA> a = new List<ProductA>();
List<ProductB> b = new List<ProductB>();

Func<ProductA, bool> findFunction = (p) => p.Id == id;

var p = a.FirstOrDefault(findFunction);
p = b.FirstOrDefault(findFunction);