Próbuję zrobić przeciążenia operatorów dla +=
, ale nie mogę. Mogę tylko przeciążać operatora +
.
Dlaczego?
Edytować
Powodem, dla którego to nie działa, jest to, że mam klasę Vector (z polami X i Y). Rozważmy następujący przykład.
vector1 += vector2;
Jeśli moje przeciążenie operatora jest ustawione na:
public static Vector operator +(Vector left, Vector right)
{
return new Vector(right.x + left.x, right.y + left.y);
}
Wtedy wynik nie zostanie dodany do vector1, ale zamiast tego vector1 stanie się zupełnie nowym Vector przez odniesienie.
Odpowiedzi:
Operatory z możliwością przeciążenia z możliwością , z MSDN:
Co więcej, żaden z operatorów przypisania nie może być przeciążony. Myślę, że dzieje się tak, ponieważ będzie to miało wpływ na zbieranie śmieci i zarządzanie pamięcią, co jest potencjalną luką w zabezpieczeniach w świecie silnie typizowanym CLR.
Niemniej jednak zobaczmy, czym dokładnie jest operator. Według słynnej książki Jeffreya Richtera , każdy język programowania ma swoją własną listę operatorów, która jest kompilowana w specjalnych wywołaniach metod, a sam CLR nie wie nic o operatorach. Zobaczmy więc, co dokładnie pozostaje za operatorami
+
i+=
.Zobacz ten prosty kod:
Zobaczmy kod IL dla tej instrukcji:
Teraz zobaczmy ten kod:
I kod IL do tego:
Są równi! Więc
+=
operator jest tylko cukrem syntaktycznym dla twojego programu w C # i możesz po prostu przeładować+
.Na przykład:
Ten kod zostanie skompilowany i pomyślnie uruchomiony jako:
Aktualizacja:
Zgodnie z twoją aktualizacją - jak mówi @EricLippert, naprawdę powinieneś mieć wektory jako niezmienny obiekt. Efektem dodania dwóch wektorów jest nowy wektor, a nie pierwszy o różnych rozmiarach.
Jeśli z jakiegoś powodu musisz zmienić pierwszy wektor, możesz użyć tego przeciążenia (ale jak dla mnie jest to bardzo dziwne zachowanie):
źródło
v3 = v1 + v2;
skutkowałov1
zmianą, a takżev3
jest niezwykłeMyślę, że ten link okaże się pouczający: Operatory przeciążalne
źródło
Dzieje się tak z tego samego powodu, dla którego nie można przeciążać operatora przypisania. Nie możesz napisać kodu, który wykonałby przypisanie poprawnie.
Z MSDN .
źródło
Nie możesz przeciążać,
+=
ponieważ tak naprawdę nie jest to wyjątkowy operator, to po prostu cukier składniowy .x += y
to tylko skrótowy sposób pisaniax = x + y
. Ponieważ+=
jest zdefiniowany za pomocą operatorów+
i=
, umożliwienie oddzielnego nadpisania go może spowodować problemy w przypadkach, w którychx += y
ix = x + y
nie zachowywał się dokładnie w ten sam sposób.Na niższym poziomie jest bardzo prawdopodobne, że kompilator C # skompiluje oba wyrażenia do tego samego kodu bajtowego, co oznacza, że jest bardzo prawdopodobne, że środowisko wykonawcze nie może traktować ich inaczej podczas wykonywania programu.
Rozumiem, że możesz chcieć potraktować to jako oddzielną operację: w oświadczeniu takim jak
x += 10
wiesz, że możesz zmutowaćx
obiekt w miejscu i być może zaoszczędzić trochę czasu / pamięci, zamiast tworzyć nowy obiektx + 10
przed przypisaniem go do starego odniesienia .Ale rozważ ten kod:
Powinien
a == b
na końcu? W przypadku większości typów nie,a
wynosi 10 więcej niżb
. Ale jeśli mógłbyś przeciążać+=
operatora, aby dokonać mutacji w miejscu, to tak. Teraz rozważ toa
ib
może zostać przekazane do odległych części programu. Możliwa optymalizacja może spowodować mylące błędy, jeśli obiekt zacznie się zmieniać tam, gdzie kod tego nie oczekuje.Innymi słowy, jeśli wydajność jest tak ważna, nie jest trudno ją zastąpić
x += 10
wywołaniem metody, takim jakx.increaseBy(10)
i jest to o wiele jaśniejsze dla wszystkich zaangażowanych.źródło
it's just syntactic sugar
nait's just syntactic sugar in C#
; w przeciwnym razie brzmi zbyt ogólnie, ale w niektórych językach programowania nie jest to tylko cukier syntaktyczny, ale może w rzeczywistości dawać korzyści wydajnościowe.+=
Prawdopodobnie mógłby zostać zoptymalizowany przez inteligentny kompilator, ponieważ arytmetyka jest prosta. Ale kiedy masz do czynienia z przedmiotami, wszystkie zakłady są wyłączone. Każdy język ma prawie takie same problemy. Dlatego przeciążenie operatora jest złe.Dzieje się tak, ponieważ ten operator nie może zostać przeciążony:
MSDN
Po prostu przeciąż
+
operatora, ponieważx += y
równyx = x + y
źródło
Przeciążenie operatora dla
+
jest używane w+=
operatorze,A += B
jest równeA = operator+(A, B)
.źródło
Jeśli przeciążasz
+
operatora w ten sposób:możesz to zrobić
lub
Spowoduje to kompilację i równe działanie.
źródło
Zawsze istnieje ta sama odpowiedź na ten problem: po co ci ten plik
+=
, jeśli otrzymasz go za darmo, jeśli przeładujesz plik+
. Ale co się stanie, jeśli mam taką klasę.Czy nadal mówisz, że to dobrze, że
+=
jest „automatycznie wdrażany”. Jeśli próbujesz wykonywać obliczenia o wysokiej wydajności w C #, musisz mieć takie funkcje, aby skrócić czas przetwarzania i zużycie pamięci, jeśli ktoś ma dobre rozwiązanie, jest to bardzo cenne, ale nie mów mi, że muszę to robić metodami statycznymi , jest to tylko obejście i nie widzę powodu, dla którego C # wykonuje+=
implementację, jeśli nie jest zdefiniowana, a jeśli jest zdefiniowana, zostanie użyta. Niektórzy mówią, że brak różnicy między błędami+
i+=
zapobieganie im, ale czy to nie jest mój własny problem?źródło
+=
jest twoim własnym problemem ... jest to prawdą tylko wtedy, gdy nikt inny nigdy nie musi czytać, utrzymywać ani wykonywać twojego kodu.List<T>
pomocą operatora takiego jaklist += "new item"
. Zamiast tego wywołujesz jegoAdd
metodę.Miałem dokładnie to samo pytanie i prawdopodobnie nie mogę na nie odpowiedzieć lepiej niż ta osoba
źródło
Lepszą metodą projektowania jest rzutowanie jawne. Zdecydowanie możesz przeciążać Casting.
źródło