在匿名方法、lambda 表达式、查询表达式或本地函数中使用的通用参数类型

Generic parameter type to use inside an anonymous method, lambda expression, query expression, or local function

我是 C# 的新手,我正在尝试创建一个接受通用参数类型的方法,如 Javascript。

假设我有一个 User 对象列表,其中包含 nameid 属性。

在 Javascript 中,使用 属性 值搜索列表非常简单:

class User{
    constructor(name, id){
        this.name = name;
        this.id = id;
    }
}

let users = [
    new User("John",1),
    new User("Deer", 2),
    new User("Bruce", 3),
    ]

function findArr(arr, propertyName, propertyValue){
    for(let a of arr)
        if(a[propertyName] === propertyValue) 
            return a;
    return null;
}

console.log(findArr(users, "name", "Deer"))
console.log(findArr(users, "id", 3))

然后,我尝试在 C# 中重新创建它:

using System;
using System.Collections.Generic;
using System.Linq;

public class User{
    public string name {get; set;}
    public int id {get; set;}
}

public class HelloWorld
{
    public static void Main(string[] args)
    {
        List<User> Users = new List<User>{
            new User{name="John", id=1},
            new User{name="Deer", id=2},
            new User{name="Bruce", id=3}
        };
        
        int propertyValue = 2;
        var u = FindList<User, int>(Users, "id", ref propertyValue);
        Console.WriteLine(u.name + " " + u.id);
    }
    
    public static T FindList<T, K>(List<T> obj, string propertyName, ref K propertyValue){
        return (T)obj.FirstOrDefault(o=>
                (K)o.GetType().GetProperty(propertyName).GetValue(o, null) 
                == 
                propertyValue
            );
    }
}

但这会抛出异常:Cannot use ref, out, or in parameter 'propertyValue' inside an anonymous method, lambda expression, query expression, or local function.

为什么抛出这个异常?

我该如何进行这项工作?

如错误消息所述,您不能在匿名函数中使用 ref 或 out 关键字。这是设计使然,详见 this answer.

好消息是,您根本不需要使用 ref。您只需将 属性 值作为普通参数传递即可实现您想要的效果,如下所示:

public static T FindList<T, K>(List<T> obj, string propertyName, K propertyValue){
    return (T)obj.FirstOrDefault(o=>
EqualityComparer<K>.Default.Equals((K)o.GetType().GetProperty(propertyName).GetValue(o, null) , propertyValue));
}

请注意,== 运算符 won't work 的相等性检查通常用于不受约束的泛型类型,因此我们改用 EqualityComparer 方法。

Javascript是一种弱类型语言,每个对象本质上只是一个字典。

如果您发现自己在 C# 中按名称访问属性,您可能做错了什么。

您可以传入一个函数来访问 属性;

而不是使用反射
    public static T FindList<T, V>(List<T> obj, Func<T,V> propertyAccess, V propertyValue){
        return obj.FirstOrDefault(o => propertyAccess(o) == propertyValue);
    }

var u = FindList<User, int>(Users, u => u.id, propertyValue);

但是,我认为此方法不会真正为您的 C# 代码添加任何内容。你最好只写直接的解决方案,不要用你自己的“帮助”方法使任何事情复杂化;

var u = Users.FirstOrDefault(u => u.id == propertyValue);

这与您熟悉的javascript代码不一样。但是您现在正在用 C# 编写。如果您想与其他 C# 程序员一起工作,您将需要改变您对编程问题的思考方式。