Pelatihan
Modul
Melakukan operasi pada array menggunakan metode helper di C# - Training
Gunakan metode pembantu C# untuk melakukan operasi membalikkan, mengubah ukuran, memisahkan, dan menggabungkan pada array.
Browser ini sudah tidak didukung.
Mutakhirkan ke Microsoft Edge untuk memanfaatkan fitur, pembaruan keamanan, dan dukungan teknis terkini.
Language-Integrated Query (LINQ) menyediakan kemampuan kueri tingkat bahasa, dan API fungsi yang lebih berurutan ke C# dan Visual Basic, yang memungkinkan Anda menulis kode deklaratif ekspresif.
Ini adalah sintaks kueri tingkat bahasa pemrogram:
var linqExperts = from p in programmers
where p.IsNewToLINQ
select new LINQExpert(p);
Dim linqExperts = From p in programmers
Where p.IsNewToLINQ
Select New LINQExpert(p)
Ini adalah contoh yang sama menggunakan API IEnumerable<T>
:
var linqExperts = programmers.Where(p => p.IsNewToLINQ)
.Select(p => new LINQExpert(p));
Dim linqExperts = programmers.Where(Function(p) p.IsNewToLINQ).
Select(Function(p) New LINQExpert(p))
Bayangkan Anda memiliki daftar hewan peliharaan, tetapi ingin mengubahnya menjadi kamus dengan hewan peliharaan yang dapat Anda akses secara langsung menggunakan nilai RFID
-nya.
Ini adalah kode imperatif tradisional:
var petLookup = new Dictionary<int, Pet>();
foreach (var pet in pets)
{
petLookup.Add(pet.RFID, pet);
}
Dim petLookup = New Dictionary(Of Integer, Pet)()
For Each pet in pets
petLookup.Add(pet.RFID, pet)
Next
Niat di balik kode bukan untuk membuat Dictionary<int, Pet>
baru dan menambahkannya melalui perulangan, namun untuk mengonversi daftar yang ada menjadi kamus! LINQ mempertahankan niat sedangkan kode imperatif tidak.
Ini adalah ekspresi LINQ yang setara:
var petLookup = pets.ToDictionary(pet => pet.RFID);
Dim petLookup = pets.ToDictionary(Function(pet) pet.RFID)
Kode yang menggunakan LINQ sangat berharga karena meratakan bidang bermain antara niat dan kode ketika melakukan pertimbangan sebagai programmer. Bonus lainnya adalah ringkasnya kode. Bayangkan mengurangi sebagian besar basis kode hingga 1/3 seperti yang dilakukan di atas. Kesepakatan yang menguntungkan, bukan?
Untuk sebagian besar perangkat lunak yang ada, semua urusannya berputar di sekitar data dari beberapa sumber (Database, JSON, XML, dan sebagainya). Ini sering kali melibatkan pembelajaran API baru untuk setiap sumber data, yang dapat mengganggu. LINQ menyederhanakan ini dengan mengabstraksi elemen umum akses data ke dalam sintaks kueri yang terlihat sama terlepas dari sumber data mana pun yang Anda pilih.
Ini menemukan semua elemen XML dengan nilai atribut tertentu:
public static IEnumerable<XElement> FindAllElementsWithAttribute(XElement documentRoot, string elementName,
string attributeName, string value)
{
return from el in documentRoot.Elements(elementName)
where (string)el.Element(attributeName) == value
select el;
}
Public Shared Function FindAllElementsWithAttribute(documentRoot As XElement, elementName As String,
attributeName As String, value As String) As IEnumerable(Of XElement)
Return From el In documentRoot.Elements(elementName)
Where el.Element(attributeName).ToString() = value
Select el
End Function
Menulis kode untuk secara manual mengunjungi dokumen XML untuk melakukan tugas ini akan jauh lebih menantang.
Berinteraksi dengan XML bukan satu-satunya hal yang dapat Anda lakukan dengan Penyedia LINQ. Linq ke SQL adalah Pemeta Relasional Objek (ORM) yang cukup mendasar untuk Database Server MSSQL. Pustaka Json.NET menyediakan traversal Dokumen JSON yang efisien melalui LINQ. Selain itu, jika tidak ada pustaka dengan fungsi yang Anda butuhkan, Anda juga dapat menulis Penyedia LINQ Anda sendiri!
Mengapa menggunakan sintaks kueri? Ini adalah pertanyaan yang sering muncul. Bagaimana pun, kode berikut:
var filteredItems = myItems.Where(item => item.Foo);
Dim filteredItems = myItems.Where(Function(item) item.Foo)
Jauh lebih ringkas daripada ini:
var filteredItems = from item in myItems
where item.Foo
select item;
Dim filteredItems = From item In myItems
Where item.Foo
Select item
Bukankah sintaks API adalah cara yang lebih ringkas untuk melakukan sintaks kueri?
Nomor. Sintaks kueri memungkinkan penggunaan klausul let, yang memungkinkan Anda memperkenalkan dan mengikat variabel dalam cakupan ekspresi, menggunakannya di bagian ekspresi berikutnya. Menghasilkan ulang kode yang sama hanya dengan sintaks API memang dapat dilakukan, tetapi kemungkinan besar akan berujung pada kode yang sulit dibaca.
Sehingga ini memunculkan pertanyaan, haruskah Anda hanya menggunakan sintaks kueri?
Jawaban atas pertanyaan ini adalah ya jika:
Jawaban atas pertanyaan ini adalah tidak jika...
Untuk daftar sampel LINQ yang benar-benar komprehensif, kunjungi 101 Sampel LINQ.
Contoh-contoh berikut adalah demonstrasi singkat dari beberapa bagian LINQ yang penting. Contoh ini sama sekali tidak komprehensif, karena LINQ menyediakan jauh lebih banyak fungsionalitas daripada yang ditunjukkan di sini.
// Filtering a list.
var germanShepherds = dogs.Where(dog => dog.Breed == DogBreed.GermanShepherd);
// Using the query syntax.
var queryGermanShepherds = from dog in dogs
where dog.Breed == DogBreed.GermanShepherd
select dog;
// Mapping a list from type A to type B.
var cats = dogs.Select(dog => dog.TurnIntoACat());
// Using the query syntax.
var queryCats = from dog in dogs
select dog.TurnIntoACat();
// Summing the lengths of a set of strings.
int seed = 0;
int sumOfStrings = strings.Aggregate(seed, (s1, s2) => s1.Length + s2.Length);
' Filtering a list.
Dim germanShepherds = dogs.Where(Function(dog) dog.Breed = DogBreed.GermanShepherd)
' Using the query syntax.
Dim queryGermanShepherds = From dog In dogs
Where dog.Breed = DogBreed.GermanShepherd
Select dog
' Mapping a list from type A to type B.
Dim cats = dogs.Select(Function(dog) dog.TurnIntoACat())
' Using the query syntax.
Dim queryCats = From dog In dogs
Select dog.TurnIntoACat()
' Summing the lengths of a set of strings.
Dim seed As Integer = 0
Dim sumOfStrings As Integer = strings.Aggregate(seed, Function(s1, s2) s1.Length + s2.Length)
// Transforms the list of kennels into a list of all their dogs.
var allDogsFromKennels = kennels.SelectMany(kennel => kennel.Dogs);
' Transforms the list of kennels into a list of all their dogs.
Dim allDogsFromKennels = kennels.SelectMany(Function(kennel) kennel.Dogs)
public class DogHairLengthComparer : IEqualityComparer<Dog>
{
public bool Equals(Dog a, Dog b)
{
if (a == null && b == null)
{
return true;
}
else if ((a == null && b != null) ||
(a != null && b == null))
{
return false;
}
else
{
return a.HairLengthType == b.HairLengthType;
}
}
public int GetHashCode(Dog d)
{
// Default hashcode is enough here, as these are simple objects.
return d.GetHashCode();
}
}
...
// Gets all the short-haired dogs between two different kennels.
var allShortHairedDogs = kennel1.Dogs.Union(kennel2.Dogs, new DogHairLengthComparer());
Public Class DogHairLengthComparer
Inherits IEqualityComparer(Of Dog)
Public Function Equals(a As Dog,b As Dog) As Boolean
If a Is Nothing AndAlso b Is Nothing Then
Return True
ElseIf (a Is Nothing AndAlso b IsNot Nothing) OrElse (a IsNot Nothing AndAlso b Is Nothing) Then
Return False
Else
Return a.HairLengthType = b.HairLengthType
End If
End Function
Public Function GetHashCode(d As Dog) As Integer
' Default hashcode is enough here, as these are simple objects.
Return d.GetHashCode()
End Function
End Class
...
' Gets all the short-haired dogs between two different kennels.
Dim allShortHairedDogs = kennel1.Dogs.Union(kennel2.Dogs, New DogHairLengthComparer())
// Gets the volunteers who spend share time with two humane societies.
var volunteers = humaneSociety1.Volunteers.Intersect(humaneSociety2.Volunteers,
new VolunteerTimeComparer());
' Gets the volunteers who spend share time with two humane societies.
Dim volunteers = humaneSociety1.Volunteers.Intersect(humaneSociety2.Volunteers,
New VolunteerTimeComparer())
// Get driving directions, ordering by if it's toll-free before estimated driving time.
var results = DirectionsProcessor.GetDirections(start, end)
.OrderBy(direction => direction.HasNoTolls)
.ThenBy(direction => direction.EstimatedTime);
' Get driving directions, ordering by if it's toll-free before estimated driving time.
Dim results = DirectionsProcessor.GetDirections(start, end).
OrderBy(Function(direction) direction.HasNoTolls).
ThenBy(Function(direction) direction.EstimatedTime)
Terakhir, sampel yang lebih canggih: menentukan apakah nilai properti dari dua instans dengan jenis yang sama telah setara (Dipinjam dan dimodifikasi dari posting StackOverflow ini):
public static bool PublicInstancePropertiesEqual<T>(this T self, T to, params string[] ignore) where T : class
{
if (self == null || to == null)
{
return self == to;
}
// Selects the properties which have unequal values into a sequence of those properties.
var unequalProperties = from property in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance)
where !ignore.Contains(property.Name)
let selfValue = property.GetValue(self, null)
let toValue = property.GetValue(to, null)
where !Equals(selfValue, toValue)
select property;
return !unequalProperties.Any();
}
<System.Runtime.CompilerServices.Extension()>
Public Function PublicInstancePropertiesEqual(Of T As Class)(self As T, [to] As T, ParamArray ignore As String()) As Boolean
If self Is Nothing OrElse [to] Is Nothing Then
Return self Is [to]
End If
' Selects the properties which have unequal values into a sequence of those properties.
Dim unequalProperties = From [property] In GetType(T).GetProperties(BindingFlags.Public Or BindingFlags.Instance)
Where Not ignore.Contains([property].Name)
Let selfValue = [property].GetValue(self, Nothing)
Let toValue = [property].GetValue([to], Nothing)
Where Not Equals(selfValue, toValue) Select [property]
Return Not unequalProperties.Any()
End Function
PLINQ, atau LINQ Paralel, adalah mesin eksekusi paralel untuk ekspresi LINQ. Dengan kata lain, ekspresi LINQ biasa dapat diparalelkan dengan mudah di sejumlah alur. Hal ini dicapai melalui panggilan ke AsParallel()
sebelum ekspresi.
Pertimbangkan skenario berikut:
public static string GetAllFacebookUserLikesMessage(IEnumerable<FacebookUser> facebookUsers)
{
var seed = default(UInt64);
Func<UInt64, UInt64, UInt64> threadAccumulator = (t1, t2) => t1 + t2;
Func<UInt64, UInt64, UInt64> threadResultAccumulator = (t1, t2) => t1 + t2;
Func<Uint64, string> resultSelector = total => $"Facebook has {total} likes!";
return facebookUsers.AsParallel()
.Aggregate(seed, threadAccumulator, threadResultAccumulator, resultSelector);
}
Public Shared GetAllFacebookUserLikesMessage(facebookUsers As IEnumerable(Of FacebookUser)) As String
{
Dim seed As UInt64 = 0
Dim threadAccumulator As Func(Of UInt64, UInt64, UInt64) = Function(t1, t2) t1 + t2
Dim threadResultAccumulator As Func(Of UInt64, UInt64, UInt64) = Function(t1, t2) t1 + t2
Dim resultSelector As Func(Of Uint64, string) = Function(total) $"Facebook has {total} likes!"
Return facebookUsers.AsParallel().
Aggregate(seed, threadAccumulator, threadResultAccumulator, resultSelector)
}
Kode ini akan mempartisi facebookUsers
di seluruh alur sistem sesuai yang diperlukan, merangkum total kesamaan pada setiap alur secara paralel, menjumlahkan hasil yang dikomputasi oleh setiap alur, dan proyek yang menghasilkan string yang bagus.
Dalam bentuk diagram:
Pekerjaan terikat CPU yang dapat diparalelkan bisa dengan mudah diekspresikan melalui LINQ (dengan kata lain, itu adalah fungsi murni dan tidak memiliki efek samping) adalah kandidat yang bagus untuk PLINQ. Untuk pekerjaan yang memiliki efek samping, pertimbangkan untuk menggunakan Pustaka Paralel Tugas.
Pelatihan
Modul
Melakukan operasi pada array menggunakan metode helper di C# - Training
Gunakan metode pembantu C# untuk melakukan operasi membalikkan, mengubah ukuran, memisahkan, dan menggabungkan pada array.