SoFunction
Updated on 2025-03-06

Detailed explanation of the introduction to LINQ (Part 1)

Preface

existPrevious articleThis simply shares the basic concepts and basic grammar of LINQ. If you have not read the previous article, you can click here. Thank you for your support, in this article we will further learn some related features and application methods of LINQ. Without further ado, please read it.

Delay loading

In the previous article, I briefly mentioned to you that LINQ has a very interesting feature, which is "delay loading" (or "delay calculation"). What is delay loading? Let's first look at the official description: delayed execution means delay in the calculation of the expression until its implementation value is really needed. Do you think it’s a bit awkward? According to my personal understanding, in layman's terms, whenever we write a LINQ expression, the sequence variable represented by this expression is just a proxy. The compiler does not miss this code when executing the compilation. After checking the syntax correctness, it skips directly. Until the code is dynamically run by the compiler and the linq expression it proxyes will not be executed when the compiler dynamically runs the sequence variable and is called in other code blocks. Ah~~Will you feel dizzy when you see this? How do you understand it? No nonsense code:

// A sequence is knownvar array = new int[] {1, 2, 3};

// Write a LINQ expression to obtain a sequence variable query// Note that this variable is just a proxy. When performing compilation, the compiler completes checking// Skip it directly after the correctness of the code and ignore itvar query = from arr in array
      where arr > 1
      select arr;

// Call the above sequence variable query, and the above LINQ expression will be executed at this time.  Note that it is already there// Execute under the compiler Runtimeforeach(var q in query)
  (());

If you think the above examples do not give you a deep understanding, please see the examples from MSDN

public static class LocalExtensions
{
  public static IEnumerable<string>
   ConvertCollectionToUpperCase(this IEnumerable<string> source)
  {
    foreach (string str in source)
    {
      ("ToUpper: source {0}", str);
      yield return ();
    }
  }
}

class Program
{
  static void Main(string[] args)
  {
    string[] stringArray = { "abc", "def", "ghi" };
    // This method ConvertCollectionToUpperCase will not be called and checked at compile time, until the following foreach calls the variable q. This method will not be executed.    var q = from str in ()
        select str;

    foreach (string str in q)
      ("Main: str {0}", str);
  }
  }

Note that ConvertCollectionToUpperCase is a static extension method. Please review it online if you are not familiar with yeild of .net 2.0, and I won't introduce it here.

// Output result

// ToUpper: source abc

// Main: str ABC

// ToUpper: source def

// Main: str DEF

// ToUpper: source ghi

// Main: str GHI

Summary: Lazy loading is good and bad. Since the sequence is executed in the case of Runtime, it is easy to cause unknown exceptions, breakpoint errors, etc., so the encoding LINQ must be taken into account its characteristics.

lambda expression

After understanding the lazy loading, we now need to simply learn the new feature lambda expression brought to us by .net 3.5. In the comments in the previous article, a gardener asked what the relationship between lambda and linq is. In fact, they have nothing to do with it, they are completely different things, but why should we master it? Because a large number of lambda expressions will be used in subsequent learning, it can make our code more elegant and readable, greatly improving our coding efficiency.

So before learning lambda, let’s review the commission delegate brought to us by .net 2.0. You will definitely not feel unfamiliar with this, and you will definitely use it frequently. I won’t give a detailed introduction to the commission here. I need to review the commission and check it online. By delegating, we can get something "anonymous method". Hey, do you think it looks familiar? Haha, use the code to deepen your memories

public delegate void SomeDelegate1;
public delegate void SomeDelegate2(arg 1, arg 2);

// Anonymous methodSomeDelegate1 del1 += delegate() {...};
SomeDelegate2 del2 += delegate(arg1, arg2) {...}

In the above code, we see that in the .net 2.0 era, we can create anonymous methods through delegate to improve coding flexibility. So what does lambda have to do with this? lambda has sublimated the anonymous methods. Look at the code:

public delegate void SomeDelegate1;
public delegate void SomeDelegate2(arg 1, arg 2);

// Anonymous methodSomeDelegate1 del1 += () => {...};
SomeDelegate2 del2 += (arg1, arg2) => {...}

Haha, don't you think it's a bit incredible? Back to the point, what is a lambda expression? From the official definition: "Lambda expression" is an anonymous function that can contain expressions and statements, and can be used to create delegate or expression tree types. All Lambda expressions use the Lambda operator =>, which is read as "goes to". The left side of the Lambda operator is the input parameter (if any), and the right side contains the expression or statement block. The Lambda expression x => x * x is pronounced as "x goes to x times x". The expression tree is mentioned in the definition, which is a topic of advanced promotion. I won’t discuss it here. Let’s focus on introductory and practical applications first.

The regular lambda expression is as follows:

(parameters) => { }

When the specified delegate type has no parameters, the expression can be as follows

() => { } Example: () => {/*Execute some methods*/}

If there is only one expression in the curly braces on the right side of the expression, such as a unary expression, a binary expression, etc., or a method, then the curly braces can be omitted as follows:

(x) => x; // The simplest expression

 (x, y) => x == y;

 () => SomeMethod();

Note that if the expression on the right has curly braces "{}" and the delegate has a return type, the expression must be accompanied by the return keyword, as follows:

(x, y) => {return x == y;};

At this point, we have a certain understanding of lambad expressions. So let's expand it. In .net 3.5, ms provides us with two generic delegates, namely Fun<T> and Action <T>. They can help us save the hassle of returning to create common delegates and improve coding efficiency.

Common: They provide up to 6 parameters (any type) for delegate passing;

Differences: Fun requires that the return type must be a return type, while Action must not return type, and it is stipulated that the return void is returned.

Example:

Fun<int, int, bool> fun = (a, b) => a==b;
Action<string> action = (p) => (p);

Summary, lambda is a love and hate for me personally, but love it a little more, which makes us write less code and do more things, but once the expression content is modified during debugging, the current debugging will either stop or start over, and it would be great if ms is done more perfectly in this regard. However, it also indirectly reminds us to have good coding design thinking.

Static extension method

After talking about lambda, let’s learn more about another new feature of .net 3.5, “static expansion method”. What is static expansion method? The official definition:Extension methods enable you to "add" methods to an existing type without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are special static methods, but can be called like instance methods on extension types.. Simply put, we can add a method to a known type without passing inheritance, rewrite, etc., so that instances of the type can use the method directly. Examples are as follows:

static class A

{

  // Here p1 and p2 are only used as examples, in practice we do not necessarily need it
  public static int ExtendMethod1(this string input,string p1, string p2)

  {

     return (input + p1 + p2);

  }

 

   // Generic methods
   public static TOutput, ExtendMethod2&lt;TOutput&gt;(this obj);

   {

      return (TOutput)obj;

   }

}

class B
{
void Main()
  {
   var a = "1";
   var result = a.ExtendMethod1("2","3");
   // result:123
  }
}

Note that the static method is necessary and needs to be in a static class. The first parameter this is required, followed by this type instance parameter that needs to be extended, which is also necessary. As for the subsequent method calls and passing parameters, it is necessary for personal needs.

Since we have learned the static expansion method, what does it have to do with LINQ? There are a large number of static extension methods provided in the namespace, which themselves encapsulate linq expressions, so that we can eliminate the steps of writing simple linq expressions. as follows:

var array = new int[]{1,2,3,4,5};

 

var query1 = from arr in array

       select arr;

 

var query2 = (e => e);

In the above example, query1 and query2 are equivalent. Can we be lazy again through query2? Haha.

Somewhere

var array = new int[]{1,2,3,4,5};

 

var query1 = from arr in array

       where arr > 2

       select arr;

 

var query2 = (e => e > 2);

Another compound

var array = new int[]{1,2,3,4,5};

 

var max = (from arr in (e => e > 2)

      select arr).Max();

Do you think it's cool? Due to the length of the article, I will not accept these static methods one by one. Below is a list of some commonly used static methods. If you are interested, go to MSDN to check it out for details.

Aggregate , All , Any , AsEnumerable , Average , Cast , Concat , Contains, Count, DefaultIfEmpty , Distinct , ElementAt, ElementAtOrDefault ,Empty , Except , First, FirstOrDefault , GroupBy , GroupJoin , Intersect , Join , Last , LastOrDefault , LongCount , Max , Min , OfType ,OrderBy ,OrderByDescending , Range , Repeat , Reverse , Select , SelectMany , SequenceEqual , Single , SingleOrDefault , Skip , SkipWhile , Sum ,Take, TakeWhile , ThenBy , ThenByDescending , ToArray , ToDictionary , ToList, ToLookup, Union,Where

Cast<T> and OfType<T> static extension methods

Finally, we should pay attention to two commonly used static methods, Cast<T>, OfType<T>. The common point they all convert sets of non-IEnumerable<T> types into IEnumerable<T> types, and then

Perform LINQ operation as follows

var dt = new DataTable();
("A", typeof(int));

var newRow1 = ();
newRow1["A"] = 1;

var newRow2 = ();
newRow2["A"] = 2;

(newRow1);
(newRow2);

var query1 = <DataRow>().Select(e=>(int)e["A"]);
var query2 = <DataRow>().Select(e=>(int)e["A"]);

In this way, we can get two identical sequences. Note here: the explanation on MSDN is misleading, and MSDN has a bias in the interpretation of OfType<T>. In fact, after I repeatedly typing the code, the conclusion is that Cast casts the sequence and throws an exception once the conversion is unsuccessful. OfType will not throw an exception once the conversion is unsuccessful, but an empty sequence will be obtained. See the following code:

var arr1 = new string[] { "1","2","test" };
var arr2 = &lt;int&gt;();
var arr3 = &lt;int&gt;();

// Convert via Cast, an exception will be thrownforeach (var i in arr2)
   (());

//Convert through OfType, there is an exception but will not be thrown and an empty sequence will be obtained.foreach (var i in arr3)
   (());

();

Summarize

At this point in this article, we have gained a further understanding of the applications involved in LINQ. Learn what is lazy loading of linq and whether lambda and linq have an ambiguous relationship. And the auxiliary effect of static expansion methods on linq. Maybe you will ask that since you can use static extension methods to write linq instead, how can you choose the two? According to the suggestion of the brick-namer, we should first focus on the static extension method in the linq namespace. It is really a very complex linq expression. Let's consider using linq itself to write. In the future, we will share the knowledge that learning LINQ is closer to practical applications, linq to dataset, linq to , linq to sql, linq to entities.

Thank you for reading. Please correct me if there is anything wrong.

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.