Operator niepodpisanego przesunięcia w prawo
Notatka
Ten artykuł jest specyfikacją funkcji. Specyfikacja służy jako dokument projektowy dla funkcji. Zawiera proponowane zmiany specyfikacji wraz z informacjami wymaganymi podczas projektowania i opracowywania funkcji. Te artykuły są publikowane do momentu sfinalizowania proponowanych zmian specyfikacji i włączenia ich do obecnej specyfikacji ECMA.
Mogą wystąpić pewne rozbieżności między specyfikacją funkcji a ukończoną implementacją. Te różnice są przechwytywane w odpowiednich spotkania projektowego języka (LDM).
Więcej informacji na temat procesu wdrażania specyfikacji funkcji można znaleźć w standardzie języka C# w artykule dotyczącym specyfikacji .
Streszczenie
Operator bezznakowego przesunięcia w prawo będzie obsługiwany przez C# jako operator zdefiniowany przez użytkownika i jako wbudowany operator dla typów całkowitych.
Motywacja
Podczas pracy z podpisaną wartością całkowitą nie jest rzadkością, że trzeba przesuwać bity w prawo bez replikowania bitu o wysokiej kolejności na każdym przesunięciu. Chociaż można to osiągnąć dla określonych typów pierwotnych całkowitych za pomocą standardowego operatora przesunięcia, konieczne jest rzutowanie na typ niepodpisany przed operacją przesunięcia, a następnie rzutowanie z powrotem po jej wykonaniu. W kontekście ogólnych interfejsów matematycznych, które biblioteki planują udostępnić, może to być bardziej problematyczne, ponieważ typ może nie mieć zdefiniowanego lub wcześniej znanego niepodpisanego odpowiednika w ogólnym kodzie matematycznym, a algorytm może polegać na możliwości wykonania niepodpisanej operacji przesunięcia w prawo.
Szczegółowy projekt
Operatory i znaki interpunkcyjne
Sekcja §6.4.6 zostanie dostosowana w celu uwzględnienia operatora >>>
- operatora niepodpisanego przesunięcia prawego:
unsigned_right_shift
: '>>>'
;
unsigned_right_shift_assignment
: '>>>='
;
Żadne znaki dowolnego rodzaju (nawet białe znaki) nie są dozwolone między tokenami w konstrukcjach unsigned_right_shift i unsigned_right_shift_assignment. Te produkcje są traktowane w szczególny sposób, aby umożliwić poprawną obsługę list typu_parametrów .
Operatory przesunięcia
Sekcja §12.11 zostanie dostosowana w celu uwzględnienia operatora >>>
- operatora niepodpisanego przesunięcia prawego:
Operatory <<
, >>
i >>>
służą do wykonywania operacji przesunięcia bitów.
shift_expression
: additive_expression
| shift_expression '<<' additive_expression
| shift_expression right_shift additive_expression
| shift_expression unsigned_right_shift additive_expression
;
W przypadku operacji formularza x << count
lub x >> count
lub x >>> count
funkcja rozpoznawania przeciążenia operatora binarnego (§12.4.5) jest stosowana w celu wybrania określonej implementacji operatora. Operandy są konwertowane na typy parametrów wybranego operatora, a typ wyniku jest zwracanym typem operatora.
Wstępnie zdefiniowane niepodpisane operatory przesunięcia będą obsługiwać ten sam zestaw podpisów, które obecnie obsługują wstępnie zdefiniowane operatory przesunięcia w bieżącej implementacji.
Shift w prawo:
int operator >>>(int x, int count); uint operator >>>(uint x, int count); long operator >>>(long x, int count); ulong operator >>>(ulong x, int count); nint operator >>>(nint x, int count); nuint operator >>>(nuint x, int count);
Operator
>>>
zmieniax
w prawo przez kilka bitów obliczonych zgodnie z poniższym opisem.Bity o niskiej kolejności
x
są odrzucane, pozostałe bity są przesunięte w prawo, a puste pozycje bitów o wysokiej kolejności są ustawione na zero.
W przypadku wstępnie zdefiniowanych operatorów liczba bitów do przesunięcia jest obliczana w następujący sposób:
- Gdy typ
x
jestint
lubuint
, liczba przesunięć jest określana przez pięć najmłodszych bitówcount
. Innymi słowy, liczba zmian jest obliczana zcount & 0x1F
. - Gdy typ
x
tolong
lubulong
, liczba przesunięć jest podawana przez sześć najmniej znaczących bitówcount
. Innymi słowy, liczba zmian jest obliczana zcount & 0x3F
.
Jeśli wynikowa liczba zmian wynosi zero, operatory przesunięcia po prostu zwracają wartość x
.
Operacje przesunięcia nigdy nie powodują przepełnienia i generują te same wyniki w kontekstach checked
i unchecked
.
Operatory przypisania
Sekcja §12.21 zostanie skorygowana w celu uwzględnienia unsigned_right_shift_assignment w następujący sposób:
assignment_operator
: '='
| '+='
| '-='
| '*='
| '/='
| '%='
| '&='
| '|='
| '^='
| '<<='
| right_shift_assignment
| unsigned_right_shift_assignment
;
Typy całkowite
Sekcja dotyczącą typów całkowitych §8.3.6 zostanie dostosowana, aby uwzględnić informacje o operatorze >>>
. Istotny punkt jest następujący:
- W przypadku operatorów
<<
binarnych ,>>
i>>>
lewy operand jest konwertowany na typT
, gdzieT
jest pierwszym zint
,uint
,long
iulong
, które mogą w pełni reprezentować wszystkie możliwe wartości operandu. Następnie operacja jest wykonywana przy użyciu precyzji typuT
, a typ wyniku jestT
.
Wyrażenia stałe
Operator >>>
zostanie dodany do zestawu konstrukcji dozwolonych w wyrażeniach stałych w §12.23.
Przeciążenie operatora
Operator >>>
zostanie dodany do zestawu przeciążalnych operatorów binarnych w §12.4.3.
Operatory zniesione
Operator >>>
zostanie dodany do zestawu operatorów binarnych pozwalających na podniesioną formę w §12.4.8.
Pierwszeństwo operatora i asocjacyjność
Sekcja §12.4.2 zostanie dostosowana w celu dodania operatora >>>
do kategorii "Shift" i operatora >>>=
do kategorii "Przypisanie i wyrażenie lambda".
Niejednoznaczności gramatyczne
Operator >>>
podlega tym samym niejednoznacznościom gramatycznym opisanym w §6.2.5 jako zwykły operator >>
.
Operatorów
Sekcja §15.10 zostanie dostosowana w celu uwzględnienia operatora >>>
.
overloadable_binary_operator
: '+' | '-' | '*' | '/' | '%' | '&' | '|' | '^' | '<<'
| right_shift | unsigned_right_shift | '==' | '!=' | '>' | '<' | '>=' | '<='
;
Operatory binarne
Podpis operatora >>>
podlega tym samym zasadom, co zasady w §15.10.3 dla podpisu operatora >>
.
Nazwa metadanych
Sekcja "I.10.3.2 Operatory binarne" ECMA-335 już zarezerwowała nazwę operatora niepodpisanego przesunięcia prawego — op_UnsignedRightShift.
Drzewa wyrażeń Linq
Operator >>>
nie będzie obsługiwany w drzewach wyrażeń Linq, ponieważ semantyka wstępnie zdefiniowanych operatorów >>>
w typach podpisanych nie może być dokładnie reprezentowana bez dodawania konwersji do niepodpisanego typu i z powrotem. Aby uzyskać więcej informacji, zobacz https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator.
Powiązanie dynamiczne
Wygląda na to, że powiązanie dynamiczne używa wartości z wyliczenia System.Linq.Expressions.ExpressionType, aby przekazać typ operatora binarnego do łącznika środowiska uruchomieniowego. Ponieważ nie mamy elementu członkowskiego reprezentującego niepodpisany operator przesunięcia prawego, powiązanie dynamiczne dla operatora >>>
nie będzie obsługiwane, a powiązanie statyczne i dynamiczne (§12.3) zostanie dostosowane, aby to odzwierciedlić.
Wady
Alternatywy
Drzewa wyrażeń Linq
Operator >>>
będzie obsługiwany w drzewach wyrażeń Linq.
- W przypadku operatora zdefiniowanego przez użytkownika zostanie utworzony węzeł BinaryExpression wskazujący metodę operatora.
- Dla wstępnie zdefiniowanych operatorów
- gdy pierwszy operand jest typem bez znaku, zostanie utworzony węzeł typu BinaryExpression.
- gdy pierwszy operand jest typem ze znakiem, zostanie dodana konwersja pierwszego operandu na typ bez znaku, zostanie utworzony węzeł BinaryExpression i zostanie dodana konwersja wyniku z powrotem do typu ze znakiem.
Na przykład:
Expression<System.Func<int, int, int>> z = (x, y) => x >>> y; // (x, y) => Convert((Convert(x, UInt32) >> y), Int32)
Resolution:
Odrzucono, zobacz https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator, aby uzyskać więcej informacji.
Nierozwiązane pytania
Spotkania projektowe
https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md
C# feature specifications