Atspindi parametrų pavadinimą: piktnaudžiavimas lambda C # išraiškomis ar sintaksės ryškumu?

Žiūriu į „ MvcContrib“ tinklelio komponentą, ir aš žaviuosi, bet tuo pačiu metu atgailauju sintaksės triukas, naudojamas „ Grid“ sintaksėje :

 .Attributes(style => "width:100%") 

Anksčiau pateikta sintaksė nustato sugeneruoto HTML stiliaus atributą į width:100% . Dabar, jei pastebėsite, kad „stilius“ nenurodytas, jis išvestas iš parametro pavadinimo išraiška! Aš turėjau eiti į jį ir atradau, kur vyksta „magija“:

  Hash(params Func<object, TValue>[] hash) { foreach (var func in hash) { Add(func.Method.GetParameters()[0].Name, func(null)); } } 

Tiesą sakant, kodas naudoja oficialų, sukomponuotą laiko parametrų pavadinimą, kad būtų sukurtas vardų atributų porų žodynas. Suteikta sintaksinė konstrukcija yra labai išraiškinga, tačiau tuo pat metu labai pavojinga. Paprastai naudojant lambda išraiškas galima pakeisti vardus, kurie naudojami be šalutinio poveikio. Matau pavyzdį knygoje, kuri sako collection.ForEach(book => Fire.Burn(book)) Aš žinau, kad galiu rašyti savo collection.ForEach(log => Fire.Burn(log)) kodas collection.ForEach(log => Fire.Burn(log)) , o tai reiškia tas pats. Bet su „MvcContrib“ tinklelio sintaksė, čia staiga aš rasiu kodą, kuris aktyviai ieško ir priima sprendimus, remdamasis vardais, kuriuos pasirinksiu kintamiesiems!

Taigi, ar tai yra įprasta praktika su C # 3.5 / 4.0 bendruomenės ir lambda išraiškos mėgėjams? Arba tai yra gudrus triukas, kurį neturėčiau nerimauti?

401
12 нояб. įkūrė Remus Rusanu 12 nov. 2009-11-12 00:00 '09 nuo 0:00 2009-11-12 00:00
ответ 21 atsakymas

Tai bloga sąveika. Pavyzdžiui, apsvarstykite šį C # - F # pavyzdį.

Su #:

 public class Class1 { public static void Foo(Func<object, string> f) { Console.WriteLine(f.Method.GetParameters()[0].Name); } } 

F #:

 Class1.Foo(fun yadda -> "hello") 

Rezultatas:

„arg“ spausdinamas (ne „yadda“).

Todėl bibliotekų kūrėjai turėtų vengti tokių „piktnaudžiavimų“ arba bent jau pateikti „standartinį“ perkrovą (pvz., Jei eilutės pavadinimą pasirinko kaip neprivalomą parametrą), jei jie nori turėti gerą sąsają. Grynos kalbos.

144
12 нояб. Atsakymą pateikė Brian lapkričio 12 d. 2009-11-12 00:10 '09 0:10 2009-11-12 00:10

Man atrodo keista, ne tiek dėl pavadinimo, bet ir dėl to, kad lambda nėra reikalinga ; jis gali naudoti anoniminį tipą ir būti lankstesnis:

 .Attributes(new { style = "width:100%", @class="foo", blip=123 }); 
border=0

Tai yra šablonas, naudojamas daugelyje ASP.NET MVC (pvz.), O kiti naudoja ( įspėjimas , taip pat atkreipkite dėmesį ir į Ayende mintis , jei pavadinimas yra stebuklinga, o ne skambintojas, konkretus)

150
12 нояб. Atsakymą pateikė Marc Gravell 12 nov. 2009-11-12 00:35 '09 - 0:35 2009-11-12 00:35

Aš tik norėjau išreikšti savo nuomonę (esu „MvcContrib“ tinklo komponento autorius).

Tai neabejotinai yra piktnaudžiavimas kalba. Tačiau aš nemanau, kad tai intuityvus - kai žiūrite į skambutį Attributes(style => "width:100%", @class => "foo")
Manau, kad tai gana akivaizdu, kas vyksta (tai tikrai nėra blogesnė nei anoniminis požiūris). Intellisense požiūriu sutinku, kad jis yra gana neskaidrus.

Tiems, kurie domisi, pateikiama tam tikra informacija apie jos naudojimą „MvcContrib“ ...

Pridėjau šį tinklą kaip asmeninį pasirinkimą - nemėgstu naudoti anoniminius tipus, nes žodynai (su parametru, kuris priima „objektą“ yra lygiai taip pat neskaidrūs, kaip ir Func [] parametrai), ir rinkimo iniciatorius yra gana žodis ( Taip pat nesu gerbėjų sąsajų ventiliatorius, pavyzdžiui, kai kurie skambučiai sujungti į atributą ("stilius", "ekranas: ne"). Atributas ("klasė", "foo") ir tt)

Jei C # buvo mažiau išsamią žodynų literatūros sintaksę, tada aš nesijaudinčiau, įskaitant šią sintaksę tinklelio komponente :)

Taip pat norėčiau pabrėžti, kad tai naudojant „MvcContrib“ yra visiškai neprivaloma - tai pratęsimo metodai, kuriais atliekami perkrovimai, naudojantys „IDictionary“. Manau, kad svarbu, jei pateikiate tokį metodą, taip pat turėtumėte paremti „normalesnį“ požiūrį, pavyzdžiui, bendrauti su kitomis kalbomis.

Be to, kas nors paminėjo „mąstymo galvą“, ir aš tik norėjau pabrėžti, kad šis požiūris neturi daug pridėtinės vertės - nesusijęs su vykdymo trukmės atspindžiu ar išraiškos sudarymu (žr. Http: //blog.bittercoder. com / PermaLink, guid, 206e64d1-29ae-4362-874b-83f5b103727f.aspx ).

136
02 дек. Atsakymą pateikė Jeremy Skinner. 2009-12-02 13:27 '09, 13:27 2009-12-02 13:27

Norėčiau

 Attributes.Add(string name, string value); 

Tai daug aiškiau ir standartiškiau, ir neveikia naudojant lambdas.

48
12 нояб. Atsakymą pateikė „ NotDan “ lapkričio 12 d. 2009-11-12 00:06 '09 - 0:06 2009-11-12 00:06

Sveiki atvykę į „Rails Land“ :)

Nėra nieko blogo, jei žinote, kas vyksta. (Tai yra, kai toks dalykas nėra gerai dokumentuotas, kad yra problema).

Visa bėgių struktūra yra pagrįsta sąlyginės konfigūracijos idėja. Tam tikru būdu įvardijami dalykai suteikia jums raktą į susitarimą, kurį jie naudoja, ir jūs jį visiškai nemokamai. Vadovaudamiesi pavadinimo konvencija, einate ten, kur važiuojate greičiau. Visa tai puikiai veikia.

Kita vieta, kur pamačiau tokį triuką, yra metodas teigia Moq. Jūs einate per lambda, bet lambda niekada neturi. Jie paprasčiausiai naudoja šią išraišką, kad užtikrintų, jog metodas vadinamas ir išmeta išimtį, jei ne.

46
12 нояб. Atsakymą pateikė Jason Punyon lapkričio 12 d 2009-11-12 00:09 '09 - 0:09 2009-11-12 00:09

Tai yra baisu keliais lygmenimis. Ir ne, tai neatrodo kaip Ruby. Tai piktnaudžiavimas C # ir .Net.

Buvo daug pasiūlymų, kaip padaryti jį paprastesnį: rinkmenas, anoniminius tipus, nemokamą sąsają ir pan.

Tai, kas daro tai taip blogai, yra tai, kad tai tik būdas įsivaizduoti save:

  • Kas atsitinka, kai reikia skambinti iš VB?

    .Attributes(Function(style) "width:100%")

  • Jo visiškai priešiškas intuityvus, intellisense nepadės daug suprasti, kaip perkelti medžiagą.

  • Jos nereikalingas neveiksmingumas.

  • Niekas nežino, kaip jį paremti.

  • Kokio tipo atributo argumentas yra Func<object,string> ? Kaip atskleidžiamas šis ketinimas. Kas bus jūsų intellisense dokumentacija: „Prašome ignoruoti visas objekto reikšmes“

Manau, kad jūs visiškai pateisinate jausti šiuos pasibjaurėjimo jausmus.

42
12 нояб. atsakymą pateikė Sam Saffron, lapkričio 12 d 2009-11-12 02:48 '09, 2:48 2009-11-12 02:48

Aš esu sintaksės blizgesio stovykloje, jei jie aiškiai dokumentuoja, ir atrodo kietas, su juo nekyla problemų!

40
12 нояб. Atsakymą pateikė Blindy lapkričio 12 d. 2009-11-12 00:07 '09 - 0:07 2009-11-12 00:07

Abi. Tai piktnaudžiavimas sintaksės lambda išraiškomis ir .

37
02 дек. atsakymą pateikė Arnis Lapsa 02 d. 2009-12-02 11:21 '09 11:21 am 2009-12-02 11:21

Aš beveik niekada nepatyriau tokio naudojimo. Manau, kad tai yra „netinkama“ :)

Tai nėra įprastas naudojimas, nesuderinamas su bendromis konvencijomis. Ši sintaksė turi privalumų ir trūkumų:

prieš

  • Kodas nėra intuityvus (įprastos konvencijos yra skirtingos)
  • Jis linkęs būti trapus (parametro pervadinimas nutrauks funkcionalumą).
  • Tai šiek tiek sunkiau patikrinti (kai paleidžiate API, bandymuose turėsite naudoti atspindį).
  • Jei išraiška yra labai naudojama, tai bus lėčiau, nes reikia analizuoti parametrą, o ne tik vertę (atspindėjimo kainą)

Privalumai

  • Tai suprantamesnė, kai kūrėjas sukonfigūruoja šią sintaksę.

Apatinė linija - viešoje API programoje norėčiau pasirinkti aiškesnį būdą.

21
12 нояб. Atsakymas duotas Elisui 12 nov. 2009-11-12 00:12 '09 0:12 2009-11-12 00:12

Ne, tai, žinoma, nėra įprasta praktika. Tai prieštarauja intuicijai, nėra jokio būdo tiesiog pažvelgti į kodą, kad suprastume, ką ji daro. Turėtumėte žinoti, kaip jis suprato, kaip jis naudojamas.

Užuot pateikę atributus naudodami daugybę delegatų, grandinės metodai bus aiškesni ir efektyvesni:

 .Attribute("style", "width:100%;").Attribute("class", "test") 

Nors tai šiek tiek daugiau tipo, jis yra suprantamas ir intuityvus.

18
12 нояб. Atsakymą pateikė Guffa lapkričio 12 d. 2009-11-12 00:13 '09 0:13 2009-11-12 00:13

Visa ši „siaubo“ pasipiktinimas yra senų C # vaikinų krūva, kurie pernelyg reaguoja (ir aš ilgą laiką buvau C # programuotojas ir vis dar labai didelis kalbos gerbėjas). Nėra nieko baisaus apie šią sintaksę. Tai tik bandymas padaryti sintaksę labiau panašią į tai, ką bandote išreikšti. Kuo mažiau „triukšmo“ sintaksėje, tuo lengviau suprasti programuotojas. Triukšmo mažinimas vienoje kodo eilutėje padeda tik šiek tiek, bet leiskite jam augti vis daugiau kodų, o tai pasirodo esąs didelis privalumas.

Tai autoriaus bandymas ieškoti tų pačių privalumų, kuriuos DSL suteikia jums - kai kodas tik „atrodo“, ką bandote pasakyti, jūs pasiekėte stebuklingą vietą. Galite aptarti, ar tai yra naudinga sąveikai, ar pakanka, kad anoniminiai metodai pateisintų kai kurias „sudėtingas“ išlaidas. Pakankamai teisinga ... taigi jūsų projekte turite pasirinkti teisingai: ar naudoti šią sintaksę. Bet vis dėlto ... tai protingas programuotojo bandymas daryti tai, ką visi bandome padaryti dienos pabaigoje (nesvarbu, ar tai suprantame, ar ne). Ir tai, ką mes visi stengiamės padaryti, yra toks: „Papasakokite kompiuteriui, ką mes norime, kad tai būtų kuo arčiau kalba, kaip mes galvojame apie tai, ko ji nori“.

Mes priartėjame prie mūsų nurodymų išreikšti kompiuteriais, kaip tikime viduje, raktas į programinės įrangos patogumą ir patikimumą.

EDIT: sakiau, kad „raktas yra padaryti programinę įrangą patogesnę ir tikslesnę“, o tai yra neįtikėtinai naivus, pripučiamas gyvybingumo elementas. Aš jį pakeitiau į „raktą“.

17
08 янв. Atsakymą pateikė Charlie Flowers sausio 08 d 2010-01-08 08:52 '10, 8:52, 2010-01-08 08:52

Kas nutiko:

 html.Attributes["style"] = "width:100%"; 
17
07 дек. Atsakymas, kurį pateikė Tommy Carlier 07 Dec 2009-12-07 15:00 '09 15:00 val. 2009-12-07 15:00

Ar galiu tai naudoti norint sukurti frazę?

magija lambda (n): „lambda“ funkcija naudojama tik keičiant magišką eilutę.

16
03 дек. Respondentas atsakė 03 dec. 2009-12-03 19:01 '09, 19:01, 2009-12-03 19:01

Tai vienas iš raiškos medžių privalumų - galite pažiūrėti patį kodą daugiau informacijos. Štai kaip .Where(e => e.Name == "Jamie") galima konvertuoti į lygiavertę SQL, kur yra sąlyga. Tai protingas išraiškos medžių naudojimas, nors norėčiau tikėtis, kad tai nebus toliau. Vis labiau sudėtinga greičiausiai bus sudėtingesnė nei kodas, kurį jis tikisi pakeisti, todėl manau, kad jis bus ribojamas.

12
12 нояб. Atsakymą pateikė Jamie Penney lapkričio 12 d 2009-11-12 00:06 '09 - 0:06 2009-11-12 00:06

Tai įdomus požiūris. Jei apribojote dešinę pusę išraiškos konstantų tik tada galite įgyvendinti

 Expression<Func<object, string>> 

Manau, kad tai yra tai, ko jūs tikrai norite, o ne delegatas (jūs naudojate lambda, kad gautumėte abiejų pusių pavadinimus).

 public static IDictionary<string, string> Hash(params Expression<Func<object, string>>[] hash) { Dictionary<string, string> values = new Dictionary<string,string>(); foreach (var func in hash) { values[func.Parameters[0].Name] = ((ConstantExpression)func.Body).Value.ToString(); } return values; } 

Tai gali netgi paveikti anksčiau minėtą tarptinklinio ryšio problemą.

7
03 дек. atsakymas duotas davidfowl 03 dec. 2009-12-03 14:27 '09 ne 14:27 2009-12-03 14:27

Kodas yra labai protingas, tačiau jis gali sukelti daugiau problemų, kurias jis išsprendžia.

Kaip jau minėjote, dabar yra neaiškus ryšys tarp parametro pavadinimo (stiliaus) ir HTML atributo. Kompiliavimo laiko patikrinimas neatliekamas. Jei parametro pavadinimas yra neteisingas, puslapis tikriausiai neturės prastovos klaidos pranešimo, tačiau daug sunkiau rasti loginę klaidą (nėra klaidos, bet neteisingas elgesys).

Geriausias sprendimas būtų turėti duomenų elementą, kurį būtų galima patikrinti kompiliavimo metu. Todėl vietoj to:

 .Attributes(style => "width:100%"); 

kodą su Stiliaus savybe gali patvirtinti kompiliatorius:

 .Attributes.Style = "width:100%"; 

arba net:

 .Attributes.Style.Width.Percent = 100; 

Tai labiau veikia kodo autoriams, tačiau šis metodas naudoja gebėjimą išbandyti stiprų C # tipą, kuris padeda išvengti klaidų įvedimo pirmiausia.

6
12 нояб. Chris R. Timmons atsakymas lapkričio 12 d 2009-11-12 00:23 '09 0:23 2009-11-12 00:23

IMHO, tai puikus būdas tai padaryti. Mes visi mėgstame tai, kad klasės valdytojo įvardijimas suteiks MVC valdytojui teisę? Taigi yra atvejų, kai įvardijami klausimai.

Čia taip pat labai aišku. Labai lengva suprasti, kad .Attribute( book => "something") veda prie book="something" , ir .Attribute( log => "something") bus log="something"

Manau, kad tai neturėtų būti problema, jei laikote ją kaip konvenciją. Manau, kad viskas, kas leidžia jums parašyti mažiau kodo ir padaryti aiškų ketinimą, yra gera.

5
02 дек. atsakymas pateikiamas beprotiško kodo 02 d. 2009-12-02 19:43 '09 19:43 2009-12-02 19:43

Iš tiesų, tai yra panaši į Ruby =), bent jau man, kad statinio ištekliaus naudojimas vėlesniam dinaminiam „paieškai“ netinka dizaino aplinkybėms, tikiuosi, kad šis protingas triukas yra neprivalomas šioje api.

Mes galime paveldėti iš IDictionary (ar ne) ir pateikti indeksą, kuris elgiasi kaip php masyvas, kai nereikia pridėti rakto, kad nustatytumėte vertę. Tai bus teisingas .net semantikos naudojimas ne tik C #, bet ir dokumentai, kaip ir anksčiau.

tikiuosi, kad tai padės

5
Atsakymą pateikė Horacio N. Hdez. Lapkričio 12 d 2009-11-12 01:30 '09, 1:30 val. 2009-11-12 01:30

Mano nuomone, tai yra piktnaudžiavimas lambdomis.

Kalbant apie sintaksę, atrodo, kad style=>"width:100%" tuščias. Ypač dėl => vietoj =

4
12 нояб. Atsakymą pateikia mfeingold 12 lapkričio. 2009-11-12 00:20 '09 ne 0:20 2009-11-12 00:20

Jei metodo pavadinimai (func) yra gerai pasirinkti, tai yra puikus būdas išvengti galvos skausmo (t. Y. Pridėti naują funkciją, bet pamiršote pridėti jį prie funkcijų parametrų atitikimo sąrašo). Žinoma, jums reikia jį dokumentuoti didele dalimi, ir jūs geriau automatiškai generuosite parametrus iš šios klasės funkcijų dokumentų.

3
12 нояб. Craig Trader atsakymas, lapkričio 12 d. 2009-11-12 00:18 '09 0:18 2009-11-12 00:18

Manau, kad tai nėra geresnė už „magišką liniją“. Tam aš nesu anoniminių tipų gerbėjas. Tam reikalingas griežtesnis ir griežčiau įvestas požiūris.

1
07 дек. JamesK atsakymas 07 Dec 2009-12-07 14:43 '09 ne 14:43 2009-12-07 14:43

Kiti klausimai apie žymes arba Užduoti klausimą