2010-03-19 9 views
54

Znalazłem temat na MSDN, który mówi, że tak, to jest możliwe.Czy jest możliwa automatyczna implementacja tylko do odczytu?

Zrobiłem test, który wydaje się przerwać to oświadczenie:

using System; 

namespace Test 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Foo f = new Foo("1"); 
      Console.WriteLine(f.Bar); // prints 1 
      f.Test("2"); 
      Console.WriteLine(f.Bar);// successfully prints 2 
     } 
    } 

    class Foo 
    { 
     public Foo(string b) 
     { 
      this.Bar = b; 
     } 

     public string Bar { get; private set; } 

     public void Test(string b) 
     { 
      // this would be impossible for readonly field! 
      // next error would be occur: CS0191 or CS0191 
      // A readonly field cannot be assigned to (except in a constructor or a variable initializer) 
      this.Bar = b; 
     } 
    } 
} 

Jeżeli się mylę?

+4

Myślę, że testujesz na niewłaściwy rodzaj tylko do odczytu tutaj. Twój kod mówi tylko, że nie możesz ustawić paska właściwości bezpośrednio z dowolnego miejsca spoza klasy ani z podklas (prywatnego ustawiacza). Twoje metody klas mogą nadal zmieniać zmienną, jeśli seter jest prywatny. – dbemerlin

+1

ummm ... a co z 'public readonly string Bar;'? – peterchen

+0

@dbemerlin: Mówię tylko w znaczeniu słowa kluczowego. Nie o poziomach dostępu. W witrynie MSDN znajduje się odpowiedni temat: http://msdn.microsoft.com/en-us/library/ba0a1yw2.aspx. Myślę, że istnieje tylko jeden rodzaj tylko do odczytu w języku C#. Cała reszta to po prostu wszystko inne, nie tylko do odczytu w języku C# :) – abatishchev

Odpowiedz

91

Poniższa odpowiedź została napisana z powrotem w 2010. W języku C# 6 (wydany w 2015) Państwo może pisać tylko do odczytu automatycznie wdrażane właściwości:

// This can only be assigned to in a constructor 
public int Foo { get; } 

Masz absolutną rację. Właściwie automatycznie wczytywane właściwości tylko do odczytu są obecnie niemożliwe. Osadzenie prywatnego setera nie jest tym samym, niezależnie od tego, co powiedzieliby niektóre książki i MSDN :)

Gdybym rządził światem, nie byłoby to prawdą. Kiedy w czerwcu zobaczę kilku projektantów języków na NDC 2010 (proszę, przyjdźcie!) Zamierzam spróbować przekonać, przekupić, nakłonić i generalnie utrapić się, dopóki się nie zgodzą. W końcu jest to tylko jedna cienka wafelka.

Patrząc na ten artykuł MSDN, sam tekst nie mówi, że tworzy on własność automatyczną tylko do odczytu. Tworzy niezmienny typ , używając automatycznej właściwości, i to jest poprawne. Jedynymi problematycznymi bitami są komentarze, które mówią: ... które są zdecydowanie błędne. Ramy zgadza się z nami:

var prop = typeof(Contact).GetProperty("Name"); 
Console.WriteLine(prop.CanWrite); // Prints True 
+1

Jeden * cienki wafel * cechuje się wieloma osobowymi tygodniami pracy: http://blogs.msdn.com/ericlippert/archive/2003/10/28/53298.aspx – Brian

+0

@Brian: Właśnie dlatego idę musiałem przekonywać, mostować, cajole itp :) Ale w porównaniu z wieloma innymi cechami, wierzę, że to naprawdę * byłoby * małe. –

+26

Nie musisz nas przekonywać, że to dobry pomysł; wiemy, że to dobry pomysł. Pytania są następujące: (1) jest to najlepsza możliwa funkcja, jaką możemy zrobić, biorąc pod uwagę budżet czasu i pieniędzy, jaki mamy, i (2) możemy wydać ten budżet na rozwiązanie bardziej ogólnego, trudniejszego, mniej "cienkiego" aspektu niezmienności , z czego niezmienne rekwizyty są prostym przypadkiem specjalnym?Każda wąska funkcja "specjalnego celu", którą dodamy, zwiększa złożoność gramatyki; chcemy mieć pewność, że osiągniemy dobrą wartość, jeśli chodzi o tę dodatkową złożoność. –

1

Prywatny zestaw nie jest taka sama jak readonly.

Podobnie jak w przypadku metod lub pól, słowo kluczowe private udostępnia widoczność osoby przygotowującej tylko samej klasie. Inne obiekty nie mogą używać settera, ale metody samej klasy mogą wywoływać je swobodnie. W związku z tym Twój kod testowy jest kompilowany i działa poprawnie.

Wygląda na obiekty zewnętrzne jako właściwość readonly, ale nie jest tylko do odczytu w prawdziwej definicji.

8

Właściwość jest tylko do odczytu poza klasą Foo. Myślę, że właśnie o to chodzi.

Ale to nie to samo, co oznaczanie zmiennej słowem kluczowym readonly.

6

To jest mylące. Należy odróżnić tylko do odczytu od C# readonly (co oznacza słowo kluczowe).

  • Tylko do odczytu: oznacza, że ​​nikt z zewnątrz nie może bezpośrednio do niego pisać, tylko czytać.
  • C# readonly: możesz pisać do niego w konstruktorze, a potem nigdy więcej.
+0

Nazwałbym to "tylko do odczytu" i "tylko do odczytu w C#" – abatishchev

+2

@abatischchev istnieje słowo tylko do odczytu w języku C#, co miałem na myśli –

+0

@persuade: Tak, mówię o tym też. Mam na myśli to, że coś w C# nie jest tylko do odczytu bez słowa kluczowego "tylko do odczytu". Lepiej się z tym połączyć w inny sposób. – abatishchev

1

słowo kluczowe ReadOnly w C# i VB, zrobić to samo po nałożeniu na polu. Sprawiają, że pole jest przypisywane tylko podczas inicjalizacji statycznej (jeśli jest oznaczone jako pole statyczne/współdzielone) lub podczas konstruktora.

C# nie wykorzystuje słowa kluczowego readonly dla niczego innego.

Słowo kluczowe ReadOnly w VB nabiera innego znaczenia po zastosowaniu do właściwości. W tym przypadku oznacza to po prostu, że nie ma akceptowalnego sposobu przypisania do właściwości publicznej (wewnętrznie, pole zaplecza może oczywiście zostać zmienione innym kodem wewnętrznym).

1

Nie można utworzyć automatycznej implementacji właściwości readonly. Jeśli spróbujesz skompilować klasę o własności auto realizowany otrzymasz ten błąd, jeśli nie ma zarówno pobierania i ustawiania:

„ProjectName.ClassName.Property.get” musi zadeklarować ciała, ponieważ nie jest oznaczony jako abstrakcyjny lub zewnętrzny. Automatycznie implementowane właściwości muszą definiować zarówno get, jak i set accessors.

Z wyrażeniem rozpoczynającym się od "Automatycznie" będącym częścią błędu, który nas dotyczy.

Powiązane problemy