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>> N
0 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 from
maddeleri dönüştü SelectMany
aramalar Elimizdeki let
haline maddelerini Select
kullanmak 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__AnonymousType1
2 (<> 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__AnonymousType3
2 (<> 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 AndAlso
gö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ığı
Join
ve GroupJoin
: Sorgu anlama aralık değişkenlerin kapsam join
maddelerine 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
from
cümle, join
& join..into
cümle ve let
cü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."