2011-04-25 31 views
12

Nigdy wcześniej nie pisałem o tym charakterze, więc jeśli nie jest to właściwe dla SO, po prostu nie rób tak źle moich uczuć, a ja to usuniemy.Czy specyfikacja C# (komitet zespołu?) Kiedykolwiek brała pod uwagę tę składnię tworzenia obiektów?

W interesie utrzymując wszystko zależy mi na jak najbliżej lewej krawędzi, jak to możliwe, że wciąż chcąc mógłbym napisać coś takiego:

DataService1.DataEntities dataEntities = new(constructorArg1, ...) 

myślę kolejny powód to lubię dodatkowego miejsca na ekranie nieruchomości uzyskuje się przy użyciu var, gdy typ jest już obecny po prawej stronie zadania, ale mój mózg ma zbyt wiele lat szuka typu po lewej stronie. Z drugiej strony, utknięcie w moich drogach nie jest dobrym powodem, by życzyć sobie spec ...

+2

Hmm, to ciekawe, +1. Ja też lubię to lepiej niż opcja 'var', ponieważ pobiera informacje o typie po lewej stronie, do której należy. (Teraz zejdź z mojego trawnika!) –

+18

Zauważam, że pytanie ma głosowanie na zakończenie w oparciu o "subiektywne i kłótliwe". Pytanie nie jest ani subiektywne, ani argumentacyjne; pytanie jest prostym pytaniem na temat tego, czy dana funkcja kiedykolwiek pojawiła się podczas dyskusji na spotkaniu poświęconym projektowaniu języka; to jest pytanie o obiektywny fakt. Tylko dlatego, że niewielu ludzi zna odpowiedź, nie stawia ona pytania subiektywnego ani argumentacyjnego. –

+0

@Eric, niezależnie od tego, czy pojawił się do dyskusji, czy nie, nie jest pytaniem programistycznym. To zamieni się w "o ile zostało to przedyskutowane" lub "jeśli poprą", co jest subiektywne i kłótliwe. –

Odpowiedz

24

Czy komitet projektujący C# rozważał kiedykolwiek składnię tego obiektu?

Tak, mamy. Rozważaliśmy to kilka lat temu. Jako dowód tego twierdzenia, patrz ostatni akapit mój artykuł tutaj:

http://blogs.msdn.com/b/ericlippert/archive/2009/01/26/why-no-var-on-fields.aspx

Konsensus zespołu projektowego było to, że był to „miło mieć” funkcji, ale nie na tyle przekonujące, że warto było znaczne koszty projektowania, wdrażania, testowania, dokumentowania i utrzymywania funkcji.

Zauważam również, że komentarze do wpisu na blogu, do którego dodałem, są bardzo negatywne w stosunku do funkcji; wydawało się, że wiele osób uznało składnię za nieatrakcyjną. To także wskazuje na to, że robimy tę funkcję.

Jednak proponowana składnia staje się szczególnie przyjemna, jeśli można ją połączyć z innymi funkcjami językowymi, które promują zwięzłą deklarację typów niezmiennych; jeśli zrobimy taką funkcję w hipotetycznej przyszłej wersji języka, wówczas proponowana przez nas składnia stanie się bardziej przekonująca.

Podkreślam ponadto, że ogólnie rzecz biorąc, opieramy się cechom, które wymagają wnioskowania z "zewnątrz" do "wnętrza"; wolimy ten przepływ informacji typu od środka na zewnątrz.Rozważmy na przykład ten problem:

M(new(blah)); 

Załóżmy M ma dwa przeciążeń, jedną, która pobiera C, a jeden, który zajmuje D. jest to, że "nowa C (bla)" lub "nowy D (bla)"? To może być albo. Teraz musimy przeanalizować oba! A jeśli oboje pracują, musimy dowiedzieć się, co jest lepsze.

Gorzej. Załóżmy, że masz

M(new(new(blah))); 

gdzie znowu M pobiera C i D i C ma dwa konstruktory, które biorą E lub F i D ma dwa konstruktory, które biorą G i H. Które z:

M(new C(new E(blah))); 
M(new C(new F(blah))); 
M(new D(new G(blah))); 
M(new D(new H(blah))); 

jest wybrany i dlaczego?

Kiedy dochodzisz z zewnątrz do wnętrza, szybko dostaję się w "kombinatoryczne eksplozje", gdzie liczba przypadków do przeanalizowania staje się O (c n) w głębi zagnieżdżenia.

C# czy powód w ten sposób do lambdas i to jest jedna z najtrudniejszych części kompilatora uczynienia wydajnych i poprawne, proszę mi wierzyć. Nie chcemy dodawać podobnej funkcji do konstruktorów. Gdybyśmy dodali tę składnię, prawdopodobnie ograniczyłoby się to do scenariuszy, w których typ był jednoznacznie znany, analizując lewą stronę deklaracji zmiennej lub wyrażenia przypisania.

(Jak zawsze zauważam, że rozważania Erica dotyczące hipotetycznych przyszłych funkcji językowych w niezapowiedzianych i całkowicie fikcyjnych produktach, które nie mają harmonogramów ani budżetów, mają wyłącznie charakter rozrywkowy i nie powinny być interpretowane jako obietnica jakiegokolwiek konkretnego przyszłego produktu z żadnym konkretnym zestawem funkcji)

+3

Chciałbym dowiedzieć się więcej o waszych pomysłach dotyczących hipotetycznych cech, które ułatwiają pracę z niezmiennymi typami. Brak wsparcia językowego w tym obszarze jest jedną z moich głównych kłopotów z C# obecnie. – CodesInChaos

+1

@CodeInChaos: Ta funkcja jest w tym momencie zbyt niepoprawna, aby nawet o niej pisać; pomysły, nad którymi się zastanawialiśmy, koncentrują się wokół zwięzłej składni mówiącej "jest to niezmienny zapis", a następnie automatycznie generuje dla ciebie właściwości konstruktora i akcesora - trochę jak typy anonimowe. W tej chwili jest wiele "ceremonii" wokół deklarowania niezmiennego typu, co prowadzi do wielu nudnych kodów standardowych. Byłoby miło go wyeliminować. –

+0

Ale masz 'int [] f = {1, 2, 3};' w języku C#, to znaczy, że również jest na zewnątrz do wewnątrz. Myślę, że C# może spowodować błąd dwuznaczności, gdy typ nie jest wymieniony ani na lewo, ani na prawo, kompilacji, jeśli typ jest wymieniony tylko w obu stronach, i zapobiec, jeśli prawo i lewo ocenić złe wyrażeń .. – nawfal

0

Nie jestem tego pewien, ale jeśli chcesz zachować rzeczy po lewej stronie, możesz zamiast tego użyć:

var dataEntities = new DataService1.DataEntities(constructorArg1, ...) 
+1

Druga część jego wiadomości mówi o tym, jak sądzę. –

+3

Wspomniałem, że w ostatnim akapicie mojego zadania –

2

Przesuwa się od lewej strony do tyłu do wyrażenia. A jeśli wyrażenie nie jest trywialne, staje się brzydkie dość szybko.

Możesz zrozumieć, co robi wyrażenie, po prostu patrząc na wyrażenie prawie zawsze (z wyjątkiem niektórych rodzajów wnioskowania typu lamda), a to nie jest możliwe przy użyciu Twojej składni. W przypadku lamdas zysk jest dość duży, więc skomplikowana konkluzja jest dobrym kompromisem dla lamdas, ale dodanie złożoności dla tak trywialnej cechy jest złym kompromisem dla prostej inicjalizacji zmiennej.

Możesz mieć specjalny przypadek "przypisanie do zmiennej, gdzie skrajne wyrażenie po prawej stronie jest wyrażeniem new." Brzmi dla mnie bardzo nieelegancko. Zwłaszcza, że ​​funkcja var osiąga już coś bardzo podobnego, a jednocześnie jest bardziej elastyczna.

+0

(losowe ujęcie tutaj), co jeśli był to "fooType fooIdent = var (arg1, ...)"? czy wyjątkowość słowa kluczowego var przy parametrze sprawdzi się? To znaczy - var (..) zostałby zastąpiony nowym T, a T jest dowolnym typem wyrażenia po lewej. –

+0

To nadal ma problem z wnioskiem typu od wyniku do wewnątrz. Jeśli zobaczysz 'var (arg1, ...)' nadal nie wiesz co to znaczy. Tego rodzaju wnioskowanie typu jest z pewnością możliwe, ale uniknęłoby go, chyba że zyski są znaczące. – CodesInChaos

+0

Czy gdybym przeczytał okładkę książki Smoka na okładce, zrozumiałbym? :) –

0

także jak o posiadaniu.

DataType dt; 

oznaczać takie same jak:

DataType dt = new DataType(); 

A potem:

DataType dt = { ParamOne = 1, ParamTwo = 2 }; 

jest taka sama jak:

DataType dt = new DataType(){ ParamOne = 1, ParamTwo =2 }; 
+5

Zdecydowanie ** nie **. 'DataType dt;' nie jest, i nie należy go mylić, z tym samym co 'DataType dt = new DataType();'. Ten ostatni nazywa konstruktora, to ważne rozróżnienie, które powinno być zachowane w składni. –

+1

Oczywiście nie pasuje do istniejącego języka C#. W ogóle. Ale w tym momencie chciałbym przejść do języka, który nie ma wszędzie zerowych wartości. Najczęstszym pojedynczym błędem, który widzę w kodzie jest błąd "zerowy odnośnik". Które, na pewno, pochodzi z niechlujstwa programowania, ale jest również (jak widzę) jedną wadą w projektowaniu języka C# jako języka.Jest to również niedopasowanie impedancji ze sposobem działania niektórych typów (takich jak int). – mlibby

+0

Języki, które nie mają pojęcia "null", zostały już wcześniej rozważone, ale tak naprawdę nie działają. Podobnie jak systemy numeryczne bez pojęcia 0. Jesteś zbyt ograniczony w ekspresji, bez możliwości wyrażania, no, nic. Teraz, jeśli argumentujesz, że C# powinno przesunąć się bardziej w kierunku idiomu RAII (jak w C++), to mógłbym być bardziej skłonny się z tobą zgodzić. Jest wiele problemów z modelem 'IDisposable' i myślę, że jest to źródło więcej błędów niż odwołań zerowych (szczególnie, że NRE może być łatwo złapany w czasie debugowania, podczas gdy wycieki pamięci są tricker). –

2

Jeśli chcesz utworzyć obiekt tego samego typu, jak członek używany do przechowywania go bez konieczności powtarzania nazwę typu, ty może używać "Stockton new". Minusem jest to, że musisz powtórzyć nazwę elementu podczas inicjalizacji. Oto jak to wygląda:

class Program 
    { 
       private static T New<T>(out T item) where T : new() 
       { 
           item = new T(); 

           return item; 
       } 

       static Dictionary<Int32, Int32> _member = New(out _member); 

       static void Main(string[] args) 
       { 
           Dictionary<Int32, Int32> local = New(out local); 
       } 
} 

Ponadto możemy przedłużyć ten sposób stworzyć konkretne zajęcia dla odpowiednich interfejsów z kilku prostych przeciążeń:

public static IDictionary<TKey, TValue> New<TKey, TValue>(out IDictionary<TKey, TValue> item) 
{ 
     item = new Dictionary<TKey, TValue>(); 

     return item; 
} 

public static IList<T> New<T>(out IList<T> item) 
{ 
     item = new List<T>(); 

     return item; 
} 

Teraz można napisać to:

IDictionary<Int32, Int32> local = New(out local); 

obrzydliwością, ciekawość, czy użyteczną techniką? Ty decydujesz.