Zastanawiam się, skoro wiele rzeczy można zrobić za pomocą odbicia, czy mogę zmienić prywatne pole tylko do odczytu po zakończeniu wykonywania przez konstruktora?
(uwaga: tylko ciekawość)
public class Foo
{
private readonly int bar;
public Foo(int num)
{
bar = num;
}
public int GetBar()
{
return bar;
}
}
Foo foo = new Foo(123);
Console.WriteLine(foo.GetBar()); // display 123
// reflection code here...
Console.WriteLine(foo.GetBar()); // display 456
c#
reflection
field
readonly
Ron Klein
źródło
źródło
Oczywiste jest, aby spróbować:
To działa dobrze. (Java ma inne reguły, co ciekawe - musisz jawnie ustawić,
Field
aby był dostępny, a i tak będzie działać tylko dla pól instancji.)źródło
Zgadzam się z innymi odpowiedziami, ponieważ działa to ogólnie, a zwłaszcza z komentarzem E. Lipperta, że nie jest to udokumentowane zachowanie, a zatem nie jest kodem przyszłościowym.
Jednak zauważyliśmy również inny problem. Jeśli uruchamiasz kod w środowisku z ograniczonymi uprawnieniami, możesz otrzymać wyjątek.
Właśnie mieliśmy przypadek, w którym nasz kod działał dobrze na naszych maszynach, ale otrzymaliśmy,
VerificationException
gdy kod działał w ograniczonym środowisku. Winowajcą było wezwanie do refleksji skierowane do ustawiacza pola tylko do odczytu. Zadziałało, gdy usunęliśmy ograniczenie tylko do odczytu tego pola.źródło
Zapytałeś, dlaczego chciałbyś przełamać hermetyzację w ten sposób.
Używam klasy pomocniczej jednostki do nawadniania jednostek. To używa odbicia, aby uzyskać wszystkie właściwości nowej pustej jednostki i dopasowuje nazwę właściwości / pola do kolumny w zestawie wyników i ustawia ją za pomocą propertyinfo.setvalue ().
Nie chcę, aby ktokolwiek inny mógł zmieniać wartość, ale nie chcę też podejmować wszelkich starań, aby dostosować metody hydratacji kodu dla każdej jednostki.
Wiele moich przechowywanych procesów zwraca zestawy wyników, które nie odpowiadają bezpośrednio tabelom lub widokom, więc kod ORM genów kodu nic dla mnie nie robi.
źródło
Innym prostym sposobem na zrobienie tego przy użyciu niebezpiecznego (lub możesz przekazać pole do metody C za pośrednictwem DLLImport i ustawić je tam).
źródło
Odpowiedź brzmi: tak, ale co ważniejsze:
Dlaczego miałbyś chcieć? Celowe zerwanie hermetyzacji wydaje mi się przerażająco złym pomysłem.
Używanie refleksji do zmiany pola tylko do odczytu lub stałego pola jest jak łączenie prawa niezamierzonych konsekwencji z prawem Murphy'ego .
źródło
Nie rób tego.
Właśnie spędziłem dzień na naprawianiu surrealistycznego błędu, w którym obiekty nie mogły być własnego zadeklarowanego typu.
Modyfikacja pola tylko do odczytu zadziałała raz. Ale jeśli spróbujesz go ponownie zmodyfikować, otrzymasz takie sytuacje:
Więc nie rób tego.
Było to w środowisku wykonawczym Mono (silnik gry Unity).
źródło
Chcę tylko dodać, że jeśli potrzebujesz zrobić te rzeczy do testów jednostkowych, możesz użyć:
A) Klasa PrivateObject
B) Nadal będziesz potrzebować instancji PrivateObject, ale możesz generować obiekty „Accessor” za pomocą programu Visual Studio. Instrukcje: regenerowanie prywatnych akcesoriów
Jeśli ustawiasz prywatne pola obiektu w swoim kodzie poza testami jednostkowymi, byłby to przykład „zapachu kodu” Myślę, że być może jedynym innym powodem, dla którego chciałbyś to zrobić, jest to, że masz do czynienia z osobą trzecią i nie możesz zmienić kodu klasy docelowej. Nawet wtedy prawdopodobnie zechcesz skontaktować się z firmą zewnętrzną, wyjaśnić swoją sytuację i sprawdzić, czy nie zrobią tego i nie zmienią swojego kodu, aby spełnić Twoje potrzeby.
źródło