我是c#的新手,我正在尝试创建一个方法,像Javascript一样接受泛型参数类型。
假设我有一个具有name
和id
属性的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#程序员一起工作,你需要改变你思考编程问题的方式。