Open9

C# 謎のイディオム集/謎の書き方/何と読む

いぬいぬいぬいぬ

is {}

こーゆーの
if( obj is {} ){
  //...
}
  • パターンマッチの一種
  • 意味としては obj != nullobj is not null
    • not演算子がC# 8.0以前はないので is not null の代わり
    • !=使わないのは(たぶん)演算子オーバーライド除けとか
いぬいぬいぬいぬ

class MyClass(int num, string txt){}

//クラス定義でいきなり引数
class MyClass(int num, string txt){}

//これと同じ意味
class MyClass2
{
   public MyClass2(int num, string txt){
  }
}
  • クラス定義でいきなり引数とってるやつ
  • プライマリコンストラクター
  • コンストラクタで引数とってるのと同じ意味
  • structやRecord型でもできる
    • class, struct: C# 12.0~
    • Record: C# 9.0~
    • Record struct: C# 10.0~

https://learn.microsoft.com/ja-jp/dotnet/csharp/whats-new/tutorials/primary-constructors

いぬいぬいぬいぬ

^1 / [^1]

//こういう配列があるとき。。
int[]  arr = [1,2,3,4,5];

//後ろから一つ目を指定する
var lastOneValue = arr[^1];  //5

//これと同じ意味
var lastOneValue2 = arr[arr.Length - 1];   //5
  • インデックス演算子の一種「^演算子
  • 意味としては length - n
  • インデクサ([])と組み合わせる
    • 組み合わせないで変数に突っ込むこともできる var index = ^1;
    • Index型として扱われる
  • Range型の「範囲演算子」(..)と組み合わせることも
いぬいぬいぬいぬ

.. / a.. / ..b / a..b/ [..arr] / arr is [..var sliced]


//これらは範囲演算子
var rangeZeroToLast = ..;   // 0..^0
var rangeAtoLast = a..;  // a..^0
var rangeZeroToB = ..b;  // 0..b
var rangeAtoB = a..b;

//こっちはspread要素
int[] arr = [1,2,3];
int[] spread = [..arr];   // [1,2,3]
if(arr is [..var sliced]){}  // sliced = [1,2,3]

//範囲とspreadの組み合わせ
int[] rangeSpread =  [..arr[1..^1]];  // [2]

  • ..は「範囲演算子」と「spread要素」の2パターンある
名前 前後にくっつく型 ..x x.. 書ける場所
範囲演算子 数値 色々(演算子と同じ)
spread要素 リスト(配列、コレクション) × []の中
  • 前4つはRange型の「範囲演算子」
    • ..は演算子そのものでもあるけど、それだけで最初から最後までを表す
  • 5つ目は「コレクション式」のspread要素
  • 最後の一つはパターンマッチのリストパターンと変数宣言、spread要素の組み合わせ
記法 意味 別の書き方
.. 最初から最後まで 0..^0
a.. aから最後まで a..^0
..b 最初からbまで 0..b
a..b aからb
[..arr] arrの中身を展開
is [..var sliced] マッチしたリストの中身をslicedとして宣言

https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/operators/member-access-operators#range-operator-
https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/operators/collection-expressions#spread-element

いぬいぬいぬいぬ

return default

int MyMethod(){
  return default;
}

int MyMethod2() => default;
  • 「defaultリテラル」をreturn
  • 意味は、(関数の戻り値の)初期値を返す
    • 例: intの場合は0
    • 例: object?の場合はnull
    • 例: Tの場合はT
  • return default(T)は古い書き方
    • 型のデフォルト値を求めるときは古い書き方じゃない(var defaultValueOfT = default(T);)
いぬいぬいぬいぬ

@"..." / $"...{v}..." / $@"...{v}..." / $"""...{v}..."""

//文字列の前に@つけるとエスケープが不要になる
@"..."
//文字列の前に$つけると{}の中に変数埋め込める
$"...{v}..."
//上の2つの組み合わせ
$@"...{v}..."
//生文字列リテラルでも$つけると変数埋め込める
$"""...{v}..."""
//これは生文字列リテラルじゃないので注意
@"""..."""
  • @"..." : 逐語的文字列リテラル
  • $"...{v}..." : 文字列補間
  • $@"...{v}..." : 逐語的文字列リテラル + 文字列補間
  • $"""...{v}...""" : 生文字列リテラル + 文字列補間

https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/tokens/verbatim

https://learn.microsoft.com/ja-jp/dotnet/csharp/tutorials/string-interpolation

https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/tokens/raw-string

いぬいぬいぬいぬ

is []

  • パターンマッチの一種
    • リストパターン(空のリストとマッチ)
  • 意味は配列やコレクション等の要素数ゼロチェック(兼nullチェック)
    • 長さ(LengthCount)を持ってるものの空のチェックができる
    • 文字列の場合は空文字列の判定につかえる
int[] array = [1,2,3];
List<int> list = [1,2,3];
Span<int> span = [1,2,3];
var str = "123";

var isEmptyArray = array is [];  //array != null && array.Length == 0
var isEmptyList = list is [];    //list != null && list.Count == 0;
var isEmptySpan = span is [];    //span2.Length == 0
var isEmptyString = str is [];   //str != null && str.Length == 0
  • stringstring.IsNullOrEmpty()と同じにするには
var isNullOrEmptyString = str is null or [];