Skip to content

MS_CSharp

nishi_74322014 edited this page Aug 21, 2026 · 4 revisions

C Sharp

概要

2000 年から開発が始まったマイクロソフト
アンダース・ヘルスバーグ
率いるチーム)が設計・開発したプログラミング言語。

  • 構文は C 言語や、C 言語風に構文が設計された C++ や Java などの影響がある。
  • 構文以外についてはヘルスバーグが以前の所属である Borland で設計した
    Delphi からの影響がある。
  • 標準化機構に託して自由な利用を許す(ECMA-334、ISO/IEC 23270:2003、JIS X 3015)など、
    姿勢の変化がある。

詳細

パラダイム

マルチパラダイム

  • 構造化, 命令型、宣言型、手続き型
  • イベント駆動型, オブジェクト指向
  • ジェネリック
  • リフレクション
  • 関数型, 並行計算

型付け

強い静的型付け

マネージ型・アンマネージ型

種別 内容
マネージ型 System.Object クラスから派生する型。ガベージ・コレクタの管理下に置かれる。EqualsGetHashCodeToString などの基本メソッドを実装する。
アンマネージ型 組み込み型 / ポインタ型 / 列挙型 / 構造体(参照型のフィールド・プロパティを含まない)

移行メモ: 元ページは System::Object(C++/CLI の記法)となっていたので、
C# の記法 System.Object に改めた。

他の言語との関係

  • 影響を受けた言語 — C++, Delphi, Eiffel, Java, LISP
  • 影響を与えた言語 — D言語, F#, Java, Nemerle, Vala

その他

  • プラットフォーム — Windows, macOS, Linux など
  • ライセンス — Apache ライセンス (Roslyn)

スニペット

忘れ易いスニペット置き場が欲しかったので。

変数定義

var

型推論を利用したローカル変数の宣言。一時的に使用される型を簡単に定義する。

var her = new { Name = "Jane Doe", Age = 20 };
var him = new { Name = "John Doe", Age = 20 };

dynamic

  • Dynamic Language Runtime(DLR)追加によりサポートされ、
    オブジェクトに対する操作のバインドは実行時まで遅延される。
  • Reflection やスクリプト言語との連携が容易になる。

補足: dynamicコンパイル時の型検査を放棄するため、
実行時まで誤りが表面化しない。
COM 相互運用や動的な JSON の扱いなど、
他に手段が無い場面に限るのが実務的な指針である。

ref変数

値型を参照型として扱う。

// ref戻り値をref変数で受け取る
ref int max = ref Max(ref x, ref y);
// limitとmaxは同じ値を参照する
ref int limit = ref max;

クラス定義

部分型

開発ツールなどが裏で使用していることが多い。
(ユーザー・コーディング部分と、designer 生成部分)

class MyClass { int a; int b; }

↓↓↓

partial class MyClass { int a; }
partial class MyClass { int b; }

プロパティ

自動実装プロパティ

メンバ変数+プロパティ・プロシージャの略記が可能。

private int __value;
public int Value
{
  get { return __value; }
  private set { __value = value; }
}

↓↓↓

public int Value { get; private set; }

メソッド定義

オプション引数

public int MethodB(int A = 0, int B = 0, int C = 0)
{
  return A + B + C;
}

名前付き引数

上記のオプション引数を選択的に指定できる。

public void MethodA()
{
  // 第1引数と第2引数を指定、第3引数は未指定:
  Console.WriteLine("Ans: " + MethodB(1, 2));        // Ans: 3 … 1 + 2 + 0
  // 第1引数と第3引数を指定、第2引数は未指定:
  Console.WriteLine("Ans: " + MethodB(A: 1, C: 3));  // Ans: 4 … 1 + 0 + 3
}

補足(オプション引数の注意): 既定値は呼び出し側にコンパイル時に埋め込まれる
そのため、ライブラリ側で既定値を変えても、
再コンパイルしない利用側には反映されない

公開 API では、オプション引数よりオーバーロードの方が安全である。

ジェネリック

クラスでも使用可能。STL っぽく書く(コンセプトは違うっポイ)。

匿名デリゲート / ラムダ式

匿名デリゲートに次ぐ「delegate」の拡張。

// 定義側
public IEnumerable<string> Read(string path, Func<string, string> fx)
{
  var result = new List<string>();
  using (var reader = new StreamReader(path))
  {
    while (reader.Peek() >= 0)
    {
      var line = reader.ReadLine();
      result.Add(fx(line));
    }
  }
  return result;
}
// 呼出し側
XXXX.Read("hoge.txt", s => s + ".txt");

上記のように「ActionFunc のデリゲートの型」(ラムダ式って)を使用する。

拡張メソッド

  • 継承せずにインスタンス・メソッドを追加定義。
  • 列挙型やインターフェイスにも適用可能。
  • 拡張メソッド定義側の名前空間を
    インポートしないと発見できないのがアレ
// 定義:第一引数の this に当該インスタンス・メソッドを追加
public static class StringUtil
{
  public static string Repeat(this string str, int count)
  {
    var array = new string[count];
    for (var i = 0; i < count; ++i) array[i] = str;
    return string.Concat(array);
  }
}
// 利用:どちらの例も "foofoofoofoo" を返す
StringUtil.Repeat("foo", 4);   // 静的メソッドとしての呼び出し
"foo".Repeat(4);               // 拡張メソッドとしての呼び出し

初期化

配列

int[] array1 = new int[] { 1, 3, 5, 7, 9 };

List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

Dictionary<string, string> openWith = new Dictionary<string, string>()
{
  {"txt", "notepad.exe"},
  {"bmp", "paint.exe"},
  {"dib", "paint.exe"},
  {"rtf", "wordpad.exe"}
};

// 匿名型の配列(型を省略できる。object型には解釈されずコンパイル・エラーになる)
var a = new[] { "foo", "bar", null };

オブジェクト

// member の初期化
Point p = new Point { X = 0, Y = 1 };

// member の new
var x = new Line
{
  A = { X = 1, Y = 2 },
  B = { X = 3, Y = 4 },
};

// var (anonymous type)
var anon = new { Name = "Terry", Age = 34 };

自動実装プロパティの初期化

C# 6 から自動実装プロパティの初期化が可能。

class Class1
{
    public string Auth { get; set; } = "BlahBlah";
}

演算子

typeof

System.Type type = typeof(int);

.GetType() メソッドと同じ。

int i = 0;
System.Type type = i.GetType();

sizeof

  • アンマネージ型のサイズを(バイト単位、int 型で)取得。
  • C# 2.0 以降は「組み込み型」に対する sizeof に関してのみ unsafe が不要
  • Marshal.SizeOf メソッドとは違うので注意(こちらはインスタンスのサイズ)。

移行メモ: 元ページの Marshall.SizeOf は綴りが誤り。
正しくは System.Runtime.InteropServices.Marshal.SizeOfl は 1 つ)。

nameof

  • 変数や、クラス、メソッド、プロパティなどの名前(識別子)を文字列リテラルとして取得
  • 名前空間やクラス名などで修飾されていない名前(必要なら Reflection で取得可能)

移行メモ: 元ページは「変装や、クラス、…」となっていたので
変数」に正した。

as, is式と拡張

  • is 式

    • オブジェクトに指定された型との互換性がある場合、true と評価される。
    • (拡張)後続に変数を宣言し、true と評価された場合、変数にキャストした値を代入する。
  • as 式

    • 互換性のある参照型または null 許容型間で特定の型変換を実行する。

    • 非互換の場合は、例外ではなく、null を返す。

    • 以下の 2 つのコードは等価

      expression as type;
      expression is type ? (type)expression : (type)null;

条件分岐

switch文と拡張

C# では、break; を明記するものの、フォールスルーを禁止されている。

// 定数パターン
switch (変数)
{
  case 値1:
    いくつかの文1;
    break;
  case 値2:
    いくつかの文2;
    break;
  default:
    いくつかの文;
    break;
}
// 型パターンと when 句
void Decide(object obj) {
    switch (obj) {
        case int num when num < 0:
            Console.WriteLine($"{num}は負の数です。");
            break;
        case int num:
            Console.WriteLine($"{num}を二乗すると{num * num}です。");
            break;
        case "B":
            Console.WriteLine($"これはBです。");
            break;
        case string str when str.StartsWith("H"):
            Console.WriteLine($"{str}はHから始まる文字列です。");
            break;
        case string str:
            Console.WriteLine($"{str}は文字列です。");
            break;
        case null:
            Console.WriteLine($"nullです");
            break;
        default:
            Console.WriteLine("判別できませんでした");
            break;
    }
}

補足(最新化): C# 8 以降、これは switch 式でより簡潔に書ける。

string Decide(object obj) => obj switch
{
    int num when num < 0 => $"{num}は負の数です。",
    int num              => $"{num}を二乗すると{num * num}です。",
    string s when s.StartsWith("H") => $"{s}はHから始まる文字列です。",
    string s             => $"{s}は文字列です。",
    null                 => "nullです",
    _                    => "判別できませんでした"
};

switch 式はすべての分岐で値を返すことが強制されるため、
「返し忘れ」がコンパイル時に検出される。

三項演算子

以下の例で、始めに a を評価してその評価値が、真である時は b
偽である時は c を評価してその評価値を返す。

int x = a ? b : c;

null結合演算子

// null でない最初の値を返す
object obj1 = null;
object obj2 = new object();
object obj3 = new object();
return obj1 ?? obj2 ?? obj3;   // obj2 を返す

// Nullable 型を非 Nullable 型に代入するときに便利
int? i = null;
int j = i ?? -1;

補足(現在よく使う関連構文): 本ページ執筆後に追加され、
実務で頻出するもの。

構文 内容
?. / ?[] null 条件演算子 C# 6
??= null 合体代入 C# 8
! null 免除演算子(「null でないと分かっている」の明示) C# 8
Nullable 参照型 <Nullable>enable</Nullable> で null 安全性を静的検査 C# 8
record 値ベースの等価性を持つ参照型 C# 9
is not null 否定パターン C# 9
ファイル スコープ名前空間 namespace Foo; C# 10
プライマリ コンストラクタ class Foo(int x) C# 12
コレクション式 int[] a = [1, 2, 3]; C# 12

特に Nullable 参照型は、新規プロジェクトのテンプレートで
既定有効になっており、NullReferenceException の削減に効く。

参考


Tags: 移行, .NET開発, プログラミング

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally