简体   繁体   English

在c#中,意思是=>符号

[英]in c#, meaning of => sign

There is a class named Student which has the properties Id , Name and Phone . 有一个名为Student的类,它具有IdNamePhone属性。 In a UI form there is a list of Student in the following way: 在UI表单中,以下列方式有一个Student列表:

List<Student> students=new List<Student>();

and finally there is a code for dataGridview_Cellclick event, where the below code is used: 最后有一个dataGridview_Cellclick事件的代码,其中使用了以下代码:

string id = dataGridview.Rows[e.RownIndex].Cells[0].Value.ToString();  
Student aStudent = students.Find(i=> i.Id== id);

What does the students.Find(i=> i.Id== id) do? students.Find(i=> i.Id== id)做什么? What does it mean? 这是什么意思? What is the meaning of => sign? => sign是什么意思? How does it work? 它是如何工作的?

They are call Lambda Expressions...Lambda expressions use special syntax. 它们称为Lambda表达式...... Lambda表达式使用特殊语法。 They allow functions to be used as data such as variables or fields. 它们允许将函数用作变量或字段等数据。 The lambda expression syntax uses the => operator. lambda表达式语法使用=>运算符。 This separates the parameters and statement body of the anonymous function. 这将分隔匿名函数的参数和语句体。

You can this of it as "Goes to". 你可以把它作为“去”。

The => operator can be read as "goes to" and it is always used when declaring a lambda expression. =>运算符可以读作“转到”,并且在声明lambda表达式时总是使用它。 A lambda expression allows you to use a function with executable statements as a parameter, variable or field. lambda表达式允许您将具有可执行语句的函数用作参数,变量或字段。

See this link on MSDN to understand it better. 请参阅MSDN上的此链接以更好地理解它。

This is a goes to operator (or lambda operator ), which used in lambda expressions (anonymous methods creation) to separate input variables from lambda body. 这是一个goes to操作者(或拉姆达运营商 ),其在使用lambda表达式 (匿名方法创建)对输入变量从拉姆达体分离。

In your sample students.Find(i => i.Id== id) input variable i goes to lambda body i.Id == id (ie passed as a anonymous method parameter). 在您的示例students.Find(i => i.Id== id)输入变量i转到lambda body i.Id == id (即作为匿名方法参数传递)。


Also take a look on on List<T>.Find method, which you are using. 另请查看您正在使用的List<T>.Find方法。 It accepts predicate of type T , which in your case will be Predicate<Student> . 它接受类型为T 谓词 ,在您的情况下将为Predicate<Student> Predicated is a delegate, which represents method that defines a set of criteria and determines whether the specified object meets those criteria. Predicated是一个委托,它表示定义一组条件并确定指定对象是否满足这些条件的方法。 It has following signature: 它有以下签名:

public delegate bool Predicate<in Student>(Student obj)

So, you need to pass a method, which accepts a student object and returns a bool. 所以,你需要传递一个方法,它接受一个学生对象并返回一个bool。 You can create normal named method for this: 您可以为此创建常规命名方法:

private bool IsStudentHasIdEqualTo5(Student s)
{
   return s.Id == 5;
}

And use it this way: 并以这种方式使用它:

Student aStudent = students.Find(IsStudentHasIdEqualTo5);

But you need to verify for different id values. 但是您需要验证不同的id值。 There is two options - either create field in your class, which will be available inside student predicate method, or create class, which will have both this method and field: 有两个选项 - 在您的类中创建字段,这将在学生谓词方法中可用,或创建类,它将同时具有此方法和字段:

class StudentSearcher
{
    private int _id; // capture id

    public StudentSearcher(int id)
    {
        _id = id;
    }

    // method has same signature as bool Predicate(Student obj)
    public bool VerfyId(Student s)
    {
        return s.Id == _id;
    }
}

Now you can use this named method and provide different id values for student verification: 现在,您可以使用此命名方法并为学生验证提供不同的id值:

var searcher = new StudentSearcher(id);
Student aStudent = students.Find(searcher.VerfyId);

But creating such methods and classes for each search is not very efficient. 但是为每次搜索创建这样的方法和类并不是非常有效。 This is why we have delegates (and lambdas). 这就是为什么我们有代表(和lambdas)。 Instead of declaring new named method, you can create method without name (anonymous) exactly in place where you need it, and compiler will generate usual named method for you: 您可以在您需要的地方创建没有名称(匿名)的方法,而不是声明新的命名方法,编译器将为您生成通常的命名方法:

Student aStudent = students.Find(delegate(Student s) { 
                                      return s.Id == id; 
                                 });

Exactly same code could be written in lambda syntax (delegate keyword omitted, parameter type inferred, goes to operator used to separate parameter and method body, return keyword also omitted): 完全相同的代码可以用lambda语法编写(委托关键字省略,参数类型推断, goes to运算符用于分隔参数和方法体,return关键字也省略):

Student aStudent = students.Find(s => s.Id == id);

The magic here is that compiler will generate class like one shown above behind the scene. 这里的神奇之处在于编译器将生成如上所示的类似于场景的类。 That class will have method with predicate signature, and also it will have field for capturing id to search for. 该类将具有带谓词签名的方法,并且还将具有用于捕获要搜索的id字段。

=> is a goesto operator and this expression is lambda expresion =>是一个goesto运算符,这个表达式是lambda expresion

See msdn msdn

The lambda operator separates the function argument(s) from its body. lambda运算符将函数参数与其主体分开。

(arg1,arg2...argn)
=>
{
  //body
}

The body could also be without parenthesis.. but it is still a "body". 身体也可以没有括号..但它仍然是一个“身体”。

(arg1,arg2..argn) => 1 ;

Student aStudent = students.Find(i=> i.Id== id);

Find is a Linq method that takes a lambda expression. Find是一个采用lambda表达式的Linq方法。

It will go through each element in students. 它将贯穿学生的每个元素。

The element is represented by i - although student would make more sense - and is passed into the "body". 元素由i表示 - 虽然student更有意义 - 并且被传递到“身体”。 If i.Id==id the Find method returns the student element. 如果i.Id==id则Find方法返回student元素。

  • What does students.Find(i=> i.Id== id) do? students.Find(i=> i.Id== id)做什么?

The situation is this. 情况就是这样。 You have a list of Student objects and the id of the student you are interested in. If the Student objects were stored in a collection you had defined yourself that has a Find method that takes an id and returns the student with that id, your code would look like this: 您有一个学生对象列表和您感兴趣的学生的ID。如果学生对象存储在一个集合中,您自己定义了一个带有ID的Find方法并返回具有该id的学生,您的代码看起来像这样:

Student aStudent = students.Find(id);

However, when Microsoft defined the generic List collection, they could not possibly know how it will be used -- and they did not want to know. 但是,当Microsoft定义了通用List集合时,他们可能不知道如何使用它 - 而且他们不想知道。 They wanted to give you the opportunity to use it with Student object or any other kind type you could think of. 他们希望让您有机会将它与Student对象或您能想到的任何其他类型一起使用。 But that meant that they had to give you a way to find the elements you are after by providing the information about your problem that only you know. 但这意味着他们必须通过提供只有您知道的问题信息,为您提供一种方法来找到您所追求的元素。 In this particular instance, you know that you are looking for a Student object stored in the students lists that had an Id field that matches the id you have. 在这个特定的实例中,您知道您正在寻找存储在学生列表中的Student对象,该对象的Id字段与您拥有的ID相匹配。 If I gave you an object, let us call it i , you would be able to tell me if it is the one you are looking for by performing the following check: 如果我给你一个物品,让我们称之为i ,你可以通过执行以下检查告诉我它是否是你要找的物品:

i.Id == id 

If I gave you an object called student , you would be able to perform the test student you would be able to tell me if it was the one you are after by performing the test 如果我给你一个叫做student的对象,你就可以通过执行测试来执行测试student你可以告诉我你是否是你所追求的那个

student.Id == id student.Id == id

(If you did not have the id but some other information that uniquely determines a Student object (ie a key) you would want to specify a different condition. Flexibility is important!) (如果您没有id但是其他一些唯一确定Student对象的信息(即一个键),那么您需要指定一个不同的条件。灵活性非常重要!)

So, now we reach the next question. 那么,现在我们到达下一个问题。

  • What does it mean? 这是什么意思?

    Let's create a convention. 让我们创建一个约定。 You will determine what you want to call the student object and you will provide an appropriate check that picks the student you are after. 您将确定要将学生对象称为什么,然后您将提供一个适当的检查来挑选您所学的学生。 You put the identifier that will represent that student on the left of => and the check condition on the right. 您将表示该学生的标识符放在=>的左侧,并将检查条件放在右侧。 Thus you can have something like: 因此你可以有类似的东西:

    student => student.Id == id student => student.Id == id

or if you prefer to refer to the student object under discussion i instead of student then you can write 或者如果你喜欢提到正在讨论的学生对象i不是student ,那么你可以写

i => i.Id == id i => i.Id == id

Now take a look. 现在来看看。 What is this? 这是什么? It is something that given a Student object returns a bool. 给出一个Student对象返回一个bool。 It is a function! 这是一个功能!

  • What is the meaning of => sign? => sign是什么意思?

    It is an operator that defines a function. 它是一个定义函数的运算符。 The argument is on the left hand side and the body is on the right hand side. 论点位于左侧,正文位于右侧。

  • How does it work? 它是如何工作的?

    Suppose you wanted me to write a function that takes a List argument and a function such as the one we are discussing and returns the matching student without using the Find method. 假设您希望我编写一个函数,该函数接受List参数和一个函数,例如我们正在讨论的函数,并返回匹配的学生,而不使用Find方法。 I would probably write something like this. 我可能会写这样的东西。

    Student FindStudent(List students, Func match) { foreach(Student st in students) if(match(st)) return st; 学生FindStudent(列出学生,Func匹配){foreach(学生在学生中)if(match(st))return st; return st; 返回 } }

    You will probably find everything quite familiar, except, I guess, the type Func which you can imagine is a type of functions from Students to booleans. 你可能会发现一切都很熟悉,除了我想,你可以想象的类型Func是一种从学生到布尔的函数。 I could also have used Predicate, which you can guess is a type for predicates on Students. 我也可以使用Predicate,你可以猜测它是学生谓词的一种类型。

    However, you need not need me to write this or to write this yourself because Microsoft has already done this for us. 但是,您不需要我自己写这个或自己写这个,因为Microsoft已经为我们这样做了。 The code Microsoft wrote for the Find() of the List<T> class looks very much like the above. Microsoft为List<T>类的Find()编写的代码与上面的内容非常相似。

Hope that helps! 希望有所帮助!


This should cover everything you have asked. 这应该涵盖你所要求的一切。 But to get a broader picture you may want to have a look also at: 但为了获得更广泛的图片,您可能还想看看:


A few parting notes that may help you: 一些可能对您有所帮助的离别说明:

  • Lambda expressions may have multiple arguments eg `(x,y) => x*x + y + 43' Lambda表达式可能有多个参数,例如`(x,y)=> x * x + y + 43'
  • The right-hand side of lambda expressions may be a code block eg `(x,y) => {return x*x + y + 43;}' lambda表达式的右侧可以是代码块,例如`(x,y)=> {return x * x + y + 43;}'
  • The type of a lambda expression with a string and an int parameter which returns a bool value is `Func' 带有字符串的lambda表达式的类型和返回bool值的int参数是`Func'
  • The type of a lambda expression with a string argument and an int argument that does not return anything is `Action' 带有字符串参数的lambda表达式的类型和不返回任何内容的int参数是“Action”

List<T> defines a method Find(Predicate<T> match) . List<T>定义了一个方法Find(Predicate<T> match)

Predicate<T> is a delegate which can refer to any method that matches its signature Predicate<T>是一个委托,可以引用与其签名匹配的任何方法

bool Predicate(T param)

In your case you are calling the Find method on a list of students List<Student> so the Find method expects a function that matches the following signature: 在您的情况下,您在学生List<Student>上调用Find方法,因此Find方法需要一个与以下签名匹配的函数:

bool MyFindMethod(Student param)

You could define such a method in your class like so: 您可以在类中定义这样的方法,如下所示:

bool MyFindMethod(Student param)
{
    // Logic goes here
}

and pass it to your Find method like this: 并将其传递给您的Find方法,如下所示:

students.Find(MyFindMethod)

The method you are using is small and simple so the overhead of creating a method in your class is not worth it so lambda expressions allow you to define the same method in a very concise way. 您使用的方法既小又简单,因此在您的类中创建方法的开销不值得,因此lambda表达式允许您以非常简洁的方式定义相同的方法。

s => s.Id == id

is equivalent to: 相当于:

bool AnonymousMethod(Student param)
{
    return s.Id == id;
}

The item(s) on the left hand side of the => operator are the parameters that are passed to the method and the items on the right hand side of the => operator is the method body. =>运算符左侧的项是传递给方法的参数,而=>运算符右侧的项是方法体。

Note that the compiler is smart enough to work out that the parameter ( s in my example) is of type Student so this does not need to be specified. 请注意,编译器足够聪明,可以确定参数(在我的示例中为s )是Student类型,因此不需要指定。

If you had a list of another type EG 如果你有一个其他类型的EG列表

public class Customer
{
    public string Name { get; set;}
}

public IList<Customer> customers = new List<Customer>();

then the compiler would infer that the parameter was of type Customer rather than student. 然后编译器会推断该参数是Customer类型而不是student类型。

customers.Find(c => c.Name == name);

Note that the parameter can be named anything you want but is usually kept to a single letter to keep the expression concise. 请注意,参数可以命名为您想要的任何名称,但通常保留为单个字母以使表达式简洁。

If you understand all of this you then you will see that your code 如果您了解所有这些,那么您将看到您的代码

students.Find(i => i.Id == id)

is basically calling a method that takes a Student as a parameter and evaluates it to see if it matches the criteria on the right hand side of the => operator. 基本上调用一个方法,该方法将Student作为参数并对其进行评估,以查看它是否与=>运算符右侧的条件匹配。 If the parameter meets the criteria (that is, if the students Id matches the id variable) then the expression will return true. 如果参数符合条件(即,如果学生Idid变量匹配),则表达式将返回true。 This tells the Find method that it has found a match and this object will be returned. 这告诉Find方法它已找到匹配项并将返回此对象。

I answered a similar question here which is related to WPF but an example in a different context might help your understanding. 在这里回答了一个与WPF相关的类似问题,但是在不同背景下的示例可能有助于您的理解。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM