【5min+】 這些C#的運算符您都認識嗎?

系列介紹

【五分鐘的dotnet】是一個利用您的碎片化時間來學習和豐富.net知識的博文系列。它所包含了.net體系中可能會涉及到的方方面面,好比C#的小細節,AspnetCore,微服務中的.net知識等等。
5min+不是超過5分鐘的意思,"+"是知識的增長。so,它是讓您花費5分鐘如下的時間來提高您的知識儲備量。程序員

開篇廢話

此次更新好像隔的有點過久了。剛纔在園子裏看了一下我發的最後一篇文章,好吧,還停留在2020/01/24。原本計劃春節停更一個星期的,結果Get到了一個有史以來最長的春節😂。c#

正文

對於「 + 」,「 - 」,「 * 」,「 / 」,「 is 」,「 as 」 等C#的運算符可能你們都再熟悉不過了。可是有時候你們在閱讀一些網站上的代碼或者開源項目的源碼時,會遇到一些奇奇怪怪的運算符,特別當幾個少見的運算符連在一塊兒的時候,彷彿有一種 「別人的C#和個人C#怎麼不同」 的感受。數組

隨着C#的版本更新,它爲咱們提供了許許多多的語法糖和新運算符方便咱們更流暢的來編寫代碼。當有時候遇到不認識的運算符,就會本着 「百度不行就谷歌」 的程序員大法來瘋狂操做一波。可是!! 搜索引擎他喵的竟然不認這些符號。微服務

x

因此,本文就整理了一些好玩兒的運算符作成了一個合集。若是碰到了不認識的操做符,也方便在這兒來查找。學習

先來看一段代碼吧:測試

if (isFlagged)
{
    _bits[propertyIndex / BitsPerInt] |= 1 << (propertyIndex % BitsPerInt);
}
else
{
    _bits[propertyIndex / BitsPerInt] &= ~(1 << (propertyIndex % BitsPerInt));
}
//節選自EF Core 中的結構體 「StateData」

有沒有猛的一看感受已經不認識了的樣子😭。畢竟對於我們平時開發應用層面的開發者來講,不少位運算符不多用到,一下碰到了都忘記了什麼意思。網站

各種運算符

補位運算符 ~

~ 運算符經過反轉每一個位產生其操做數的按位求補:搜索引擎

byte a = 10;   // 二進制 0000 1010
var b = (byte)~a;    // 二進制 1111 0101 。 b的十進制:245

移位運算符 <<>>

<< 運算符將其左側操做數向左移動:編碼

byte a = 10;   // 0000 1010
var b = (byte)a<<2;    // 0010 1000。  b=40

>> 運算符將其左側操做數向右移動.net

byte a = 10;   // 0000 1010
var b = (byte)a<<2;    // 0000 0010。  b=2

好比 10 * 2^3 當咱們用C#寫的時候可能會寫: 10 * Math.Pow(2,3) ,而如今能夠直接寫 10 << 3。

邏輯運算符 ^

固然邏輯運算符還有其它的幾個,好比 & 和 | ,這些平時你們用的比較多因此就很少寫了。

^ 運算符計算其操做數的位邏輯異或:

byte a = 10;   // 0000 1010
var b = a ^ 0b_0010_1011;    // 0010 0001

因此若是配上我們C#的複合運算,好比 +=-=。相應的,上面的符號就能夠寫成 >>=|= , &= , ^= 等。

byte a = 10;
a <<=2;   // 40

索引運算符 ^

沒錯,仍是這個符號。若是在索引器 [] 中使用它,它將充當索引的做用。
^ 運算符在 C# 8.0 和更高版本中提供,指示序列末尾的元素位置。例如,^1 指向序列的最後一個元素,^length 指向序列的第一個元素。

int[] xs = new[] { 0, 10, 20, 30, 40 };
int last = xs[^1];
Console.WriteLine(last);  // output: 40

因此當咱們須要逆序來訪問索引器的時候就不須要寫成 : array[array.length - i] 了,直接^i 就能夠了。

Null 條件運算符 ?.?[]

僅當操做數的計算結果爲非 null 時,null 條件運算符纔會將成員訪問 ?. 或元素訪問 ?[] 運算應用於其操做數;不然,將返回 null。

A?.B?.Do(C);
A?.B?[C];

該操做符相信不少小夥伴早就使用起來了,畢竟能夠直接省略掉咱們的 if(A==null),大幅提升了咱們的編碼流暢度。

範圍運算符 ..

這個操做符很好玩,它是最新版本C#中才更新的。
.. 運算符在 C# 8.0 和更高版本中提供,指定索引範圍的開頭和末尾做爲其操做數。

int[] numbers = new[] { 0, 10, 20, 30, 40, 50 };
int start = 1;
int amountToTake = 3;
int[] subset = numbers[start..(start + amountToTake)];
Display(subset);  // output: 10 20 30

它能夠結合上面的索引運算符 ^ 一同使用,好比:

int margin = 1;
int[] inner = numbers[margin..^margin];
Display(inner);  // output: 10 20 30 40

因此咱們就能夠不用去for循環而後再來截取原視數組的部分了。

類型測試運算符 is

該關鍵字其實你們也很熟悉,可是在C# 7以後,它新增了:有模式匹配的類型測試。

object iBoxed = i;
if (iBoxed is int a)
{
    Console.WriteLine(a);
}

在常規的類型測試表達式後面跟上一個變量,則該變量會轉換爲測試運算後的結果。這樣就不須要咱們再去作一次判斷了。

一說到這裏,我忽然想到若是之後的C#可以支持這種表達式就行了,雖然只是YY😝:

if(cacl() != null)
{
    var result = cacl();
    //use result do something 
}

//若是能更改成這樣就行了
if(cacl() result !=null)
{
    //use result do something 
}

Null 合併運算符 ??

該運算符也是很是有用的。若是左操做數的值不爲 null,則 null 合併運算符 ?? 返回該值;不然,它會計算右操做數並返回其結果。 若是左操做數的求值結果爲非 null,則 ?? 運算符不會對右操做數求值。

int? a = null;
int b = a ?? -1;
Console.WriteLine(b);  // output: -1

這樣就避免了咱們每次都會去寫一個 if(xx = null),從而大大簡化咱們的代碼。
而且它還能夠一直推算下去:

a ?? b ?? c

而在C# 8以後,??運算符還提供了合併運算的版本 ??= 。

b = b?? a;
//等同於
b??=a;

因此我們常常對List判斷是否爲空,賦予初始值的操做,如今只須要一句話就完成了:

someList ??= new List<int>()).Add(5);

再結合上面的一些操做符來使用:

double SumNumbers(List<double[]> setsOfNumbers, int indexOfSetToSum)
{
    return setsOfNumbers?[indexOfSetToSum]?.Sum() ?? double.NaN;
}

總結

因此如今我們再來看一些感受奇怪的符號就以爲天然得多了,這些運算符不知道幫助我們省略掉了多少的if- else。

本文只是選取了一些不常見的運算符來介紹,而常見的 " | "、「 & 」 ,「 ?. 」 等運算符相信你們用的也比較多了,因此就再也不說起。 還有就是關於指針的一些操做符,好比: " -> " , 「 * 」等也沒有涉及。

固然,若是您用的是最新的C#版本,你可使用全部的這些簡寫運算符,若是您使用的是以往的版本,請確保該運算符被支持喲。

本篇文章也不屬於什麼技術分享。不過有時候這些基礎的東西每每會對我們編碼提供很大的便利性。

x

相關文章
相關標籤/搜索