在匿名方法、lambda表达式、查询表达式或局部函数中使用的泛型参数类型



我是c#的新手,我正在尝试创建一个方法,像Javascript一样接受泛型参数类型。

假设我有一个具有nameid属性的User对象列表。

在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关键字。这是经过设计的,在这个回答中有详细说明。

好消息是,您根本不需要使用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));
}

请注意,使用==操作符的相等性检查通常不适用于无约束泛型类型,因此我们使用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#程序员一起工作,你需要改变你思考编程问题的方式。

相关内容

最新更新