Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharpNotesForProfessionals.pdf
Скачиваний:
57
Добавлен:
20.05.2023
Размер:
6.12 Mб
Скачать

This result has created anonymous objects on the fly, which is fine, but we have already created a proper class - so we can specify it: Instead of SELECT NEW { f.ID, s.RegionDescription }; we can say SELECT NEW Region(f.ID, s.RegionDescription);, which will return the same data but will create objects of type Region - that will maintain compatibility with the other objects.

Live demo on .NET fiddle

Section 66.7: Skip and Take

The Skip method returns a collection excluding a number of items from the beginning of the source collection. The number of items excluded is the number given as an argument. If there are less items in the collection than specified in the argument then an empty collection is returned.

The Take method returns a collection containing a number of elements from the beginning of the source collection. The number of items included is the number given as an argument. If there are less items in the collection than specified in the argument then the collection returned will contain the same elements as the source collection.

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

 

 

 

var skipTwo

= values.Skip(2);

//

{ 3, 2, 1

}

var takeThree

= values.Take(3);

//

{ 5, 4, 3

}

var

skipOneTakeTwo

= values.Skip(1).Take(2); //

{ 4, 3 }

 

var

takeZero

= values.Take(0);

//

An IEnumerable<int> with 0 items

 

 

 

 

 

 

Live Demo on .NET Fiddle

Skip and Take are commonly used together to paginate results, for instance:

IEnumerable<T> GetPage<T>(IEnumerable<T> collection, int pageNumber, int resultsPerPage) { int startIndex = (pageNumber - 1) * resultsPerPage;

return collection.Skip(startIndex).Take(resultsPerPage);

}

Warning: LINQ to Entities only supports Skip on ordered queries. If you try to use Skip without ordering you will get a NotSupportedException with the message "The method 'Skip' is only supported for sorted input in LINQ to Entities. The method 'OrderBy' must be called before the method 'Skip'."

Section 66.8: Defining a variable inside a Linq query (let keyword)

In order to define a variable inside a linq expression, you can use the let keyword. This is usually done in order to store the results of intermediate sub-queries, for example:

int[] numbers = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

var aboveAverages = from number in numbers

let average = numbers.Average() let nSquared = Math.Pow(number,2) where nSquared > average

select number;

Console.WriteLine("The average of the numbers is {0}.", numbers.Average());

foreach (int n in aboveAverages)

GoalKicker.com – C# Notes for Professionals

358

{

Console.WriteLine("Query result includes number {0} with square of {1}.", n, Math.Pow(n,2));

}

Output:

The average of the numbers is 4.5.

Query result includes number 3 with square of 9.

Query result includes number 4 with square of 16.

Query result includes number 5 with square of 25.

Query result includes number 6 with square of 36.

Query result includes number 7 with square of 49.

Query result includes number 8 with square of 64.

Query result includes number 9 with square of 81.

View Demo

Section 66.9: Zip

The Zip extension method acts upon two collections. It pairs each element in the two series together based on position. With a Func instance, we use Zip to handle elements from the two C# collections in pairs. If the series di er in size, the extra elements of the larger series will be ignored.

To take an example from the book "C# in a Nutshell",

int[] numbers = { 3, 5, 7 };

string[] words = { "three", "five", "seven", "ignored" }; IEnumerable<string> zip = numbers.Zip(words, (n, w) => n + "=" + w);

Output:

3=three

5=five

7=seven

View Demo

Section 66.10: Range and Repeat

The Range and Repeat static methods on Enumerable can be used to generate simple sequences.

Range

Enumerable.Range() generates a sequence of integers given a starting value and a count.

// Generate a collection containing the numbers 1-100 ([1, 2, 3, ..., 98, 99, 100]) var range = Enumerable.Range(1,100);

Live Demo on .NET Fiddle

Repeat

GoalKicker.com – C# Notes for Professionals

359

Enumerable.Repeat() generates a sequence of repeating elements given an element and the number of repetitions required.

// Generate a collection containing "a", three times (["a","a","a"]) var repeatedValues = Enumerable.Repeat("a", 3);

Live Demo on .NET Fiddle

Section 66.11: Basics

LINQ is largely beneficial for querying collections (or arrays).

For example, given the following sample data:

var classroom = new Classroom

{

new Student { Name = "Alice", Grade = 97, HasSnack = true }, new Student { Name = "Bob", Grade = 82, HasSnack = false }, new Student { Name = "Jimmy", Grade = 71, HasSnack = true }, new Student { Name = "Greg", Grade = 90, HasSnack = false }, new Student { Name = "Joe", Grade = 59, HasSnack = false }

}

We can "query" on this data using LINQ syntax. For example, to retrieve all students who have a snack today:

var studentsWithSnacks = from s in classroom.Students where s.HasSnack

select s;

Or, to retrieve students with a grade of 90 or above, and only return their names, not the full Student object:

var topStudentNames = from s in classroom.Students where s.Grade >= 90

select s.Name;

The LINQ feature is comprised of two syntaxes that perform the same functions, have nearly identical performance, but are written very di erently. The syntax in the example above is called query syntax. The following example, however, illustrates method syntax. The same data will be returned as in the example above, but the way the query is written is di erent.

var topStudentNames = classroom.Students

.Where(s => s.Grade >= 90)

.Select(s => s.Name);

Section 66.12: All

All is used to check, if all elements of a collection match a condition or not. see also: .Any

1. Empty parameter

All: is not allowed to be used with empty parameter.

2. Lambda expression as parameter

GoalKicker.com – C# Notes for Professionals

360

All: Returns true if all elements of collection satisfies the lambda expression and false otherwise:

var numbers = new List<int>(){ 1, 2, 3, 4, 5}; bool result = numbers.All(i => i < 10); // true bool result = numbers.All(i => i >= 3); // false

3. Empty collection

All: Returns true if the collection is empty and a lambda expression is supplied:

var numbers = new List<int>();

bool result = numbers.All(i => i >= 0); // true

Note: All will stop iteration of the collection as soon as it finds an element not matching the condition. This means that the collection will not necessarily be fully enumerated; it will only be enumerated far enough to find the first item not matching the condition.

Section 66.13: Aggregate

Aggregate Applies an accumulator function over a sequence.

int[] intList = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

int sum = intList.Aggregate((prevSum, current) => prevSum + current);

// sum = 55

At the first step prevSum = 1

At the second prevSum = prevSum(at the first step) + 2

At the i-th step prevSum = prevSum(at the (i-1) step) + i-th element of the array

string[] stringList = { "Hello", "World", "!" };

string joinedString = stringList.Aggregate((prev, current) => prev + " " + current);

// joinedString = "Hello World !"

A second overload of Aggregate also receives an seed parameter which is the initial accumulator value. This can be used to calculate multiple conditions on a collection without iterating it more than once.

List<int> items = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };

For the collection of items we want to calculate

1.The total .Count

2.The amount of even numbers

3.Collect each forth item

Using Aggregate it can be done like this:

var result = items.Aggregate(new { Total = 0, Even = 0, FourthItems = new List<int>() }, (accumelative,item) =>

new {

Total = accumelative.Total + 1,

Even = accumelative.Even + (item % 2 == 0 ? 1 : 0), FourthItems = (accumelative.Total + 1)%4 == 0 ?

new List<int>(accumelative.FourthItems) { item } : accumelative.FourthItems

});

// Result:

GoalKicker.com – C# Notes for Professionals

361