任何人都可以向我解释这一行在 c# 中的作用吗?

Can Anybody Explain to Me What This Line Does in c#?

我不明白 <...> 语法,这是函数吗? 谁能给我解释一下这行代码?

ApplyPropertyChange<AgreementTransaction, int>(ref _agreementId, o => o.AgreementId, value);

此语法:

o => o.AgreementId

就是使用了lambda operator.

具体来说,这会创建一个匿名函数,它接受一个名为 o 的参数,函数体只是 return o.AgreementId.

所以这个:

o => o.AgreementId

是这个的缩写:

delegate(var o)
{
    return o.AgreementId;
}

但是你不能像那样真正指定 var o,但是对于 lambda 运算符,编译器可以根据函数所在的委托为 o 推断出正确的类型,这是您需要转到 ApplyPropertyChange 方法的地方,它很可能看起来像这样:

public void ApplyPropertyChange<T1,T2>(ref T2 value, Func<T1,T2> getValue, T1 inputValue)

在这种情况下,T1T2 是从 o.AgreementIdref _agreementId 推断出来的。

根据方法的名称 (ApplyPropertyChange) 和参数类型,对于一组元素中的一个元素,它看起来像是 setter。 <> 的用途是传递元素的类型,在本例中它是一个 AgreementTransactionint 类型的第二个参数很可能是预期值或 Func 的结果。

ApplyPropertyChange(ref _agreementId, o => o.AgreementId, value);

看起来它正在获取元素集,使用其 AgreementId 在集合中查找元素,然后设置显示的值。

它可以在某些方面在基本层面上像这样重写。

foreach(AgreementTransaction el in setOfElements)
{
    if( (int)el.AgreementId == _agreementId )
    {
        el.AgreementId = value;
    }
}

传入的Func<>被称为谓词。它本质上是一个将 AgreementTransaction 投射到 int 中的委托。

可以这样想:

AgreementTransactions.Select( o => o.AgreementId );

或者更广泛的例子:

List<AgreementTransaction> AgreementTransactions = someListOfThem;
List<int> result = new List<int>();
foreach(AgreementTransaction agree in AgreementTransactions)
{
    result.Add(agree.AgreementId);
}

总的来说,关于 Lambda 表达式、Func 声明和委托,还有很多我不会涉及的内容。您可以从 MSDN 阅读更多相关信息:https://msdn.microsoft.com/en-us/library/bb397687.aspx

=> 是 lambda 运算符。有人说你读成"goes to"。这是代表的快捷方式。

也许上面这句话对你来说有几个新的概念。委托背后的想法是你不把值作为函数的参数,而是一个函数。实际上参数是一个值,但这个值不是一个整数,也不是一个对象;是函数类型

如果你调用像 F(x) 这样的函数并且你给一个值 4 作为参数,你会告诉这个函数,每当它看到字母 X 时应该使用值 4.

委托也一样。如果你有一个以委托 D 作为参数的函数,并且你用参数 Sin(x) 调用它,你对函数说,无论何时它使用对 D 的调用,它都应该调用 Sin(x)。

使用委托的传统方式涉及相当多的输入。随着 lambda 表达式的引入,这变得容易多了。

lambda 表达式在 Linq 中被大量使用。每当您需要使用诸如数组/列表/集合/集合之类的序列来做事时,您通常会使用 foreach Linq 会让您的生活更轻松。

例如,假设您有一系列人物。我在这里使用术语序列,因为我不关心它是一个数组、一个列表、一个集合、一个集合等等。我对它的唯一要求是我可以请求序列中的第一个元素和下一个元素,直到没有更多元素为止。简而言之:我要求序列是可枚举的。

假设从这个序列中我只想要具有 FirstName 属性 "John" 值的人。为此,使用了静态函数 Enumerable.Where。结果是与我的原始序列类型相同的 IEnumerable:

IEnumerable<Person> personsNamedJohn = Persons
    .Where(p => p.FirstName == "John");

在这里您会看到 =>。您可以将其表述为:

从 Persons 序列中取出每个人(我们称之为 p),其中 p.FirstName == "John"。

我经常通过给我的序列一个复数标识符(Persons)来保持它的可读性,而不是 p 我写单数标识符:

IEnumerable<Person> personsNamedJohn = Persons
    .Where(person => person.FirstName == "John");
IEnumerable<Shape> circles = Shapes
    .Where(shape => shape.ShapeType == Shape.Circle);

还有许多其他 Linq 函数使用了 lambda。我们看到函数 where 为您提供了与谓词匹配的序列元素。函数 Select 将使用序列中的每个项目创建另一个项目。

IEnumerable<Address> addressesOfPersonsNamedJohn = Persons
    .Where(person => person.FirstName == "John")
    .Select(person => new Address(person.Street, person.City, person.ZIP));

这是:从所有人中,只取名字为 "John" 的人,然后从每个人中取街道、城市和邮政编码 属性 作为构造函数的参数地址对象。结果是一系列地址。

一开始我觉得 lambda 运算符的使用很混乱,但是一旦理解了它,它就变得非常有用。每当我写 foreach 时,我发现如果我使用带有 lambda 表达式的 Linq 语句,它通常可以写得更短并且更容易理解。

The standard linq operatores 是我理解 linq、delegates 和 lambda 的一个很好的起点