Başka bir cevap eklemek için hiç geç oldu mu?
Bir ton LINQ-nesne kodu yazdım ve en azından bu etki alanında, hangisinin daha basit kod için yapılacağını kullanmak için her iki sözdizimini anlamanın iyi olduğunu iddia ediyorum - bu her zaman nokta sözdizimi değildir.
Elbette, nokta sözdiziminin gitme yolu IS olduğu zamanlar vardır - diğerleri bu vakaların birkaçını sağlamıştır; Ancak, anlamaların kısa değiştiğini düşünüyorum - eğer istersen kötü bir rap verilir. Bu yüzden, anlamaların yararlı olduğuna inandığım bir örnek vereceğim.
İşte bir basamaklı değiştirme bulmacasına bir çözüm: (LINQPad kullanılarak yazılmış, ancak bir konsol uygulamasında tek başına durabilir)
// NO
// NO
// NO
//+NO
//===
// OK
var solutions =
from O in Enumerable.Range(1, 8) // 1-9
//.AsQueryable()
from N in Enumerable.Range(1, 8) // 1-9
where O != N
let NO = 10 * N + O
let product = 4 * NO
where product < 100
let K = product % 10
where K != O && K != N && product / 10 == O
select new { N, O, K };
foreach(var i in solutions)
{
Console.WriteLine("N = {0}, O = {1}, K = {2}", i.N, i.O, i.K);
}
//Console.WriteLine("\nsolution expression tree\n" + solutions.Expression);
... hangi çıktılar:
N = 1, O = 6, K = 4
Çok da kötü değil, mantık doğrusal akıyor ve bunun tek bir doğru çözümle geldiğini görebiliyoruz. Bu bulmacanın elle çözmesi yeterince kolaydır: 3>> N0 ve O> 4 * N'nin 8> = O> = 4 olduğu anlamına gelir. Bu, elle test etmek için maksimum 10 vaka olduğu anlamına gelir (2 için N-by- 5 O). Yeterince başıboş oldum - bu bulmaca LINQ gösterim amacıyla sunulmuştur.
Derleyici Dönüşümleri
Derleyicinin bunu eşdeğer nokta sözdizimine çevirmek için yaptığı çok şey var. Her zamanki yanında ikinci ve sonraki frommaddeleri dönüştü SelectManyaramalar Elimizdeki lethaline maddelerini Selectkullanmak her ikisi de projeksiyonlar ile çağrılar, şeffaf-tanımlayıcıları . Göstermek üzere olduğum gibi, bu tanımlayıcıları nokta sözdiziminde adlandırmak zorunda kalmak, bu yaklaşımın okunabilirliğinden uzaklaşıyor.
Derleyicinin bu kodu nokta sözdizimine çevirmesinde ne yaptığını göstermek için bir numaram var. Yukarıdaki iki yorum satırını açıp tekrar çalıştırırsanız, aşağıdaki çıktıyı alırsınız:
N = 1, O = 6, K = 4
çözüm ifadesi ağacı System.Linq.Enumerable + d_ b8.SelectMany (O => Aralık (1, 8), (O, N) => yeni <> f _AnonymousType0 2(O = O, N = N)).Where(<>h__TransparentIdentifier0 => (<>h__TransparentIdentifier0.O != <>h__TransparentIdentifier0.N)).Select(<>h__TransparentIdentifier0 => new <>f__AnonymousType12 (<> h_ TransparentIdentifier0 = <> h _TransparentIdentifier0, NO = ((10 * <> h_ TransparentIdentifier0.N) + '' H _TransparentIdentifier0.O))). Select (<> h_ TransparentIdentifier1 => yeni <> f _AnonymousType2 2(<>h__TransparentIdentifier1 = <>h__TransparentIdentifier1, product = (4 * <>h__TransparentIdentifier1.NO))).Where(<>h__TransparentIdentifier2 => (<>h__TransparentIdentifier2.product < 100)).Select(<>h__TransparentIdentifier2 => new <>f__AnonymousType32 (<> h_ TransparentIdentifier2 = <> h _TransparentIdentifier2, K = ( <> h_ TransparentIdentifier2.product% 10))).) Nerede (<> h _TransparentIdentifier3 => ((((((<> h_ TransparentIdentifier3.K! = <> h _TransparentIdentifier3. <> h_ TransparentIdentifier2)h _TransparentIdentifier1. <> h_TransparentIdentifier0.O) AndAlso (<> h _TransparentIdentifier3.K! = <> H_ TransparentIdentifier3. <> Sa _TransparentIdentifier2. <> H_ TransparentIdentifier1. <> H _TransparentIdentifier0.N)) AndAlso ((<> h_ TransparentIdentifier3. <> H _TransparentIdentifier2. ürün / 10) == <> h_ TransparentIdentifier3. <> h _TransparentIdentifier2. <> h_ TransparentIdentifier1. <> h _TransparentIdentifier0.O))). Select (<> h_ TransparentIdentifier3 => yeni <> f _AnonymousType4`3 (n = < > h_ TransparentIdentifier3. <> h _TransparentIdentifier2. <> h_ TransparentIdentifier1. <> h _TransparentIdentifier0.N,O = <> h_ TransparentIdentifier3. <> H_TransparentIdentifier2. <> H_ TransparentIdentifier1. <> H _TransparentIdentifier0.O, K = <> h__TransparentIdentifier3.K))
Her LINQ operatörünü yeni bir satıra koymak, "konuşulamayacak" tanımlayıcıları "konuşabildiklerimize" çevirmek, anonim türleri bilinen biçimlerine değiştirmek ve derleyicinin bir eşdeğerde gelmesi için elde ettiği dönüşümleri AndAlsogöstermek için ifade ağacı dilini değiştirmek &&nokta sözdiziminde:
var solutions =
Enumerable.Range(1,8) // from O in Enumerable.Range(1,8)
.SelectMany(O => Enumerable.Range(1, 8), (O, N) => new { O = O, N = N }) // from N in Enumerable.Range(1,8)
.Where(temp0 => temp0.O != temp0.N) // where O != N
.Select(temp0 => new { temp0 = temp0, NO = 10 * temp0.N + temp0.O }) // let NO = 10 * N + O
.Select(temp1 => new { temp1 = temp1, product = 4 * temp1.NO }) // let product = 4 * NO
.Where(temp2 => temp2.product < 100) // where product < 100
.Select(temp2 => new { temp2 = temp2, K = temp2.product % 10 }) // let K = product % 10
.Where(temp3 => temp3.K != temp3.temp2.temp1.temp0.O && temp3.K != temp3.temp2.temp1.temp0.N && temp3.temp2.product / 10 == temp3.temp2.temp1.temp0.O)
// where K != O && K != N && product / 10 == O
.Select(temp3 => new { N = temp3.temp2.temp1.temp0.N, O = temp3.temp2.temp1.temp0.O, K = temp3.K });
// select new { N, O, K };
foreach(var i in solutions)
{
Console.WriteLine("N = {0}, O = {1}, K = {2}", i.N, i.O, i.K);
}
Çalıştırırsanız, tekrar çıktı olduğunu doğrulayabilirsiniz:
N = 1, O = 6, K = 4
... ama hiç böyle kod yazacak mısın?
Bahse girerim cevabı NONBHN (Sadece Hayır, Ama Cehennem Hayır!) - çünkü sadece çok karmaşık. Tabii ki "temp0" .. "temp3" den daha anlamlı bazı tanımlayıcı isimler bulabilirsin, fakat asıl nokta, koda bir şey eklemiyor olmaları - kodun daha iyi performans göstermesini sağlamazlar, kodun daha iyi okunmasını sağlayın, yalnızca kodu çirkinleştirirler ve el ile yapıyor olsaydınız, doğru yapmadan önce bir veya üç kez karıştırırsınız. Ayrıca, "isim oyununu" oynamak, anlamlı tanımlayıcılar için yeterince zor, bu yüzden derleyicinin sorgu anlamalarında bana sağladığı isim oyunundan ayrılıyorum.
Bu bulmaca örneği, ciddiye almanız için yeterli gerçek dünya olmayabilir ; ancak, sorgu anlamaların parladığı başka senaryolar vardır:
- Karmaşıklığı
Joinve GroupJoin: Sorgu anlama aralık değişkenlerin kapsam joinmaddelerine aksi anlama sözdiziminde derleme zamanı hataları içine nokta sözdiziminde derlemek olabilir hataları açın.
- Derleyici anlama dönüşümüne şeffaf bir tanımlayıcı getireceği zaman, anlama değdi. Bu, aşağıdakilerden herhangi birinin kullanımını içerir: çoklu
fromcümle, join& join..intocümle ve letcümle.
Memleketimde, anlama kavramını yasa dışı bırakan birden fazla mühendislik mağazasını tanıyorum . Sanırım bu anlama sözdizimi bir araç değil, ancak yararlı bir araç olarak üzücü. Sanırım "Bir tornavida ile yapamayacağınız şeyler var. Bir keskiyle yapamayacağınız şeyler var. Çünkü bir tornavidayı bir keski olarak kullanabilirsiniz, keskiler bundan böyle kralın kararnamesi altında yasaklanır."