使用現代化 C# 語法簡化程式碼
使用現代化 C# 語法簡化程式碼
Intro
最近幾個版本的 C# 在語法中有很多的變化,有很多語法能夠幫助我們大大簡化程式碼複雜度,使得程式碼更加簡潔,分享幾個我覺得比較實用的可以讓程式碼更加簡潔的語法
Default literal expressions
在 C# 7。1 之後,我們可以使用
default
來代替一個型別的預設值,例如:
publicvoidTest(stringstr=deault){}
stringstr=default;
在之前的版本我們需要顯式指定型別,如
default(string)
,就不需要寫型別了,編譯器會推斷出型別
Target-Typed New Expression
在 C# 9 中,引入了
Target-Typed New Expression
語法,和上面的
default
類似,我們在建立物件的時候不再需要在編譯器可以推斷出型別的地方再寫出型別了,這在有時候會很有用,尤其是在寫一個型別非常複雜的欄位的時候,我們就只需要宣告一次就可以了,可以參考下面的示例:
//target-typednewexpression
//privatestaticreadonlyDictionary
//Dictionary=newDictionary
privatestaticreadonlyDictionary
Dictionary=new();
//array
ReviewRequest[]requests=
{
new()
{
State=ReviewState。Rejected
},
new(),
new(),
};
Named Tuple
從 C# 7 開始,我們可以使用
Named Tuple
來最佳化 Tuple 的使用,在之前的版本我們只能 Item1, Item2 這樣去使用 Tuple 的 Value,但是這樣很不好理解,尤其是在沒有文件說明的情況下,可能每次都要去返回值的地方看一下究竟每一個元素代表什麼,
Named Tuple
出現了之後就相當於一個強型別的 Tuple,能夠使得程式碼更好理解,tuple 元素的含義一目瞭然,舉個栗子:
(stringAlpha,stringBeta)namedLetters=(“a”,“b”);
Console。WriteLine($“{namedLetters。Alpha},{namedLetters。Beta}”);
(intcode,stringmsg)result=(1,“”);
privatestatic(intcode,stringmsg)NamedTuple()
{
return(0,string。Empty);
}
varresult=NamedTuple();
Console。WriteLine(result。code);
Deconstruct
與
Named Tuple
同時出現的,我們可以在類中宣告一個
Deconstruct
與
Constructor
相對應,只是
Constructor
是輸入引數,
Deconstruct
是輸出引數,來看一個示例吧:
publicclassPoint
{
publicPoint(doublex,doubley)
=>(X,Y)=(x,y);
publicdoubleX{get;}
publicdoubleY{get;}
publicvoidDeconstruct(outdoublex,outdoubley)=>
(x,y)=(X,Y);
}
varp=newPoint(3。14,2。71);
(doubleX,doubleY)=p;
上面的示例是官方文件的一個示例,來看一個我們實際在用的一個示例吧:
publicclassIdNameModel
{
publicintId{get;set;}
publicstringName{get;set;}
publicvoidDeconstruct(outintid,outstringname)
{
id=Id;
name=Name;
}
}
多個返回值時,有的資料不關心可以使用 “_” 來表示丟棄返回值,示例如下:
usingSystem;
usingSystem。Collections。Generic;
publicclassExample
{
publicstaticvoidMain()
{
var(_,_,_,pop1,_,pop2)=QueryCityDataForYears(“NewYorkCity”,1960,2010);
Console。WriteLine($“Populationchange,1960to2010:{pop2-pop1:N0}”);
}
privatestatic(string,double,int,int,int,int)QueryCityDataForYears(stringname,intyear1,intyear2)
{
intpopulation1=0,population2=0;
doublearea=0;
if(name==“NewYorkCity”)
{
area=468。48;
if(year1==1960)
{
population1=7781984;
}
if(year2==2010)
{
population2=8175133;
}
return(name,area,year1,population1,year2,population2);
}
return(“”,0,0,0,0,0);
}
}
//Theexampledisplaysthefollowingoutput:
//Populationchange,1960to2010:393,149
Pattern-Matching
模式匹配最早開始於 C# 7。1,最早的形式如:
if(a is string str)
,這是最簡單也是最經典的一個模式匹配,它結合了之前需要兩句話才能完成的功能,可以翻譯成:
varstr=aasstring;
if(str!=null)//。。。
除了
if
,我們在
switch
裡也可以使用模式匹配的
voidSwitchPattern(objectobj0)
{
switch(obj0)
{
casestringstr1:
Console。WriteLine(str1);
break;
caseintnum1:
Console。WriteLine(num1);
break;
}
}
在 C# 9 中引入了邏輯運算子
and
/
or
/
not
使得模式匹配更為強大,來看一個判斷是否是合法的 Base64 字元的一個方法的變化:
C# 9 之前的程式碼:
privatestaticboolIsInvalid(charvalue)
{
varintValue=(int)value;
if(intValue>=48&&intValue<=57)
returnfalse;
if(intValue>=65&&intValue<=90)
returnfalse;
if(intValue>=97&&intValue<=122)
returnfalse;
returnintValue!=43&&intValue!=47;
}
使用 C# 9 增強的模式匹配之後的程式碼:
privatestaticboolIsInvalid(charvalue)
{
varintValue=(int)value;
returnintValueswitch
{
>=48and<=57=>false,
>=65and<=90=>false,
>=97and<=122=>false,
_=>intValue!=43&&intValue!=47
};
}
是不是一下子清晰的很多~~
Switch Expression
Switch Expression 是 C# 8 引入的新特性,C# 9 有結合模式匹配做了進一步的增強,使得其功能更加強大,來看示例吧:
修改前的程式碼是這樣的:
varstate=ReviewState。Rejected;
varstateString=string。Empty;
switch(state)
{
caseReviewState。Rejected:
stateString=“0”;
break;
caseReviewState。Reviewed:
stateString=“1”;
break;
caseReviewState。UnReviewed:
stateString=“-1”;
break;
}
使用 switch expression 之後的程式碼如下:
varstate=ReviewState。Rejected;
varstateString=stateswitch
{
ReviewState。Rejected=>“0”,
ReviewState。Reviewed=>“1”,
ReviewState。UnReviewed=>“-1”,
_=>string。Empty
};
是不是看起來簡潔了很多,還有進一步的增加最佳化,來看下一個示例:
(intcode,stringmsg)result=(0,“”);
varres=resultswitch
{
(0,_)=>“success”,
(-1,_)=>“xx”,
(-2,“”)=>“yy”,
(_,_)=>“error”
};
Console。WriteLine(res);
猜猜不同情況的輸出的結果是什麼樣的,再自己試著跑一下結果看看是不是符合預期吧
Index Range
Index/Range 是 C# 8 引入的一個新特性,主要優化了對元組的操作,可以更方便的做索引和切片操作
之前有過一篇詳細的介紹文章,可以參考:
C# 使用 Index 和 Range 簡化集合操作
我們可以透過
^
(hat) 運算子來反向索引陣列中的物件,可以透過
。。
來建立一個集合的子集合,來看一個簡單的示例:
vararr=Enumerable。Range(1,10)。ToArray();
Console。WriteLine($“lastelement:{arr[^1]}”);
varsubArray=Enumerable。Range(1,3)。ToArray();
Console。WriteLine(arr[。。3]。SequenceEqual(subArray)?“StartWith”:“No”);
Record
Record 是 C# 9 引入的新特性,record 是一個特殊的類,編譯器會幫助我們做很多事情,會自動實現一套基於值的比較,而且可以很方便實現物件複製的功能,詳細介紹可以參考之前的 record 介紹文章
C# 9 新特性 — record 解讀
,可以看下面這個簡單的示例:
publicabstractrecordPerson(stringFirstName,stringLastName);
publicrecordTeacher(stringFirstName,stringLastName,intGrade)
:Person(FirstName,LastName);
publicrecordStudent(stringFirstName,stringLastName,intGrade)
:Person(FirstName,LastName);
publicstaticvoidMain()
{
Personteacher=newTeacher(“Nancy”,“Davolio”,3);
Personstudent=newStudent(“Nancy”,“Davolio”,3);
Console。WriteLine(teacher==student);//output:False
Studentstudent2=newStudent(“Nancy”,“Davolio”,3);
Console。WriteLine(student2==student);//output:True
}
Top-Level Statement
Top-Level statement 是 C# 9 支援的新特性,我們可以不寫 Main 方法,直接寫方法體,對於一些比較簡單的小工具,小測試應用來說會比較方便
usingstaticSystem。Console;
WriteLine(“Helloworld”);
More
除了上面這些新特性,你覺得還有哪些比較實用的新特性呢,歡迎留言一起討論哈~
References
https://
docs。microsoft。com/en-u
s/dotnet/csharp/whats-new/csharp-9
https://
docs。microsoft。com/en-u
s/dotnet/csharp/whats-new/csharp-8
https://
docs。microsoft。com/en-u
s/dotnet/csharp/whats-new/csharp-7
https://
github。com/WeihanLi/Sam
plesInPractice/blob/master/CSharp9Sample/CleanCodeSample。cs
技術群:新增小編微信並備註進群
小編微信:mm1552923
公眾號:dotNet程式設計大全