共用方式為


無符號右移運算子

注意

本文是功能規格。 規格可作為功能的設計檔。 其中包含建議的規格變更,以及功能設計和開發期間所需的資訊。 這些文章會發佈,直到提議的規格變更完成並併併入目前的ECMA規格為止。

功能規格與已完成實作之間可能有一些差異。 這些差異是在的相關 語言設計會議(LDM)注意事項中擷取的。

您可以在 規格一文中深入瞭解將功能規範納入 C# 語言標準的過程

總結

C# 將支援無符號右移運算子,做為內建運算子(適用於基本整數類型),以及做為使用者定義運算子。

動機

在處理帶正負號的整數值時,常需要將位元向右移,但不希望每次移位時復制最高位元。 雖然對於原始整數類型,可以使用常規移位運算符來實現此目的,但在移位操作之前需要先將其轉換為無符號類型,並且在移位后再轉換回來。 在泛型數學介面中,庫文件計劃公開介面,這可能更具挑戰性。因為這種類型可能沒有定義或不被泛型數學程式碼事先知道的無符號對應類型,但某些演算法可能依賴於能夠執行無符號右移操作的能力。

詳細設計

運算子和標點符號

部份 第6.4.6節 將會調整為包含 >>> 運算符 - 無符號右移運算符:

unsigned_right_shift
    : '>>>'
    ;

unsigned_right_shift_assignment
    : '>>>='
    ;

unsigned_right_shiftunsigned_right_shift_assignment 語法規則中,令牌間不允許任何字元(甚至是空格符)。 這些生成會特別處理,以便正確處理 type_parameter_lists。

移位運算符

區段 §12.11 將調整為包含 >>> 運算子 - 無符號右移運算子:

<<>>>>> 運算子用於執行位元移位運算。

shift_expression
    : additive_expression
    | shift_expression '<<' additive_expression
    | shift_expression right_shift additive_expression
    | shift_expression unsigned_right_shift additive_expression
    ;

針對形式的作業 x << countx >> countx >>> count,二元運算子多載解析程序(§12.4.5)用來選取特定運算子實作。 操作數會轉換成所選取運算子的參數類型,而結果的類型是運算元的傳回類型。

預先定義的無符號移位運算子將支援當前實作中預先定義的有符號移位運算子所支援的相同簽名。

  • 右移:

    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);
    

    >>> 運算符會將 x 右移若干位元,其位數根據下述計算。

    x 的低階位捨棄後,剩餘位元向右移動,並將高階的空位設為零。

針對預先定義的運算子,要移位的位數會計算如下:

  • x 的類型是 intuint時,移位計數由 count的低階五個位元決定。 換句話說,輪班計數會從 count & 0x1F開始計算。
  • x 的類型是 longulong時,移位計數由 count的低位六個位元決定。 換句話說,輪班計數會從 count & 0x3F開始計算。

如果產生的移位計數為零,則位元移位運算子只會傳回 x的值。

位移運算永遠不會造成溢位,並在 checkedunchecked 環境中產生相同的結果。

賦值運算子

區段 §12.21 將會調整為包含 unsigned_right_shift_assignment,如下所示:

assignment_operator
    : '='
    | '+='
    | '-='
    | '*='
    | '/='
    | '%='
    | '&='
    | '|='
    | '^='
    | '<<='
    | right_shift_assignment
    | unsigned_right_shift_assignment
    ;

整數類型

將會調整整數類型 •8.3.6 區段,以包含 >>> 運算符的相關信息。 相關的項目符號如下:

  • 對於二進位 <<>>>>> 運算符,左操作數會轉換成類型 T,其中 T 是第一個 intuintlongulong,可以完整表示操作數的所有可能值。 接著,作業會使用 T類型的精確度來執行,而結果的類型會 T

常數表達式

運算子 >>> 會被新增至允許在常數運算式中的一組建構,在 §12.23

運算子多載

運算子 >>> 將會新增至 -12.4.3的可多載二進位運算符集合。

提升運算符

運算子 >>> 會被新增至一組二元運算符,允許在 §12.4.8的提升形式。

運算元優先順序和關聯性

區段 •12.4.2 將會調整,以將 >>> 運算符新增至 “Shift” 類別,並將 >>>= 運算符新增至 “Assignment and lambda expression” 類別。

文法模棱兩可

>>> 運算符的文法模棱兩可與 運算符相同,如 >> 中所述。

運營商

§15.10 區段將會調整以包含 >>> 運算符。

overloadable_binary_operator
    : '+'   | '-'   | '*'   | '/'   | '%'   | '&'   | '|'   | '^'   | '<<'
    | right_shift | unsigned_right_shift | '=='  | '!='  | '>'   | '<'   | '>='  | '<='
    ;

二元運算子

>>> 運算子的簽章受限於與 §15.10.3>> 運算符的簽章相同的規則。

元數據名稱

ECMA-335 的「I.10.3.2 二元運算子」區段已保留無符號右移運算子的名稱 - op_UnsignedRightShift。

Linq 運算式樹狀架構

Linq 表達式樹將不支援 >>> 運算符,因為有符號類型上預先定義的 >>> 運算符的語意無法正確表示,除非將轉換新增至無符號類型再轉回。 如需詳細資訊,請參閱 https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator

動態系結

看起來動態綁定會使用 System.Linq.Expressions.ExpressionType 表達式類型的值,將二元運算子的種類傳達給執行階段綁定器。 因為我們沒有一個專門代表無符號右移運算子的成員,因此將不支援 >>> 運算子的動態綁定,而靜態和動態綁定(§12.3)部分將進行調整以反映此情況。

缺點

替代方案

Linq 運算式樹狀架構

Linq 表達式樹中將支援 >>> 運算符。

  • 針對使用者定義的運算符,將會建立指向運算符方法的 BinaryExpression 節點。
  • 針對預先定義的運算符
    • 當第一個操作數是帶正負號的類型時,將會建立 BinaryExpression 節點。
    • 當第一個操作數是有符號類型時,將會新增第一個操作數到無符號類型的轉換,接著建立 BinaryExpression 節點,並將結果轉換回有符號類型。

例如:

Expression<System.Func<int, int, int>> z = (x, y) => x >>> y; // (x, y) => Convert((Convert(x, UInt32) >> y), Int32)

Resolution:

已拒絕,欲知詳情,請參閱 https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator

未解決的問題

設計會議

https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md