LoginSignup
16
10

More than 5 years have passed since last update.

C# はコンストラクタの型引数を省略できない

Last updated at Posted at 2018-11-13

コンストラクタの型引数が省略できるようでできない...

C#の型引数の省略

  • メソッドの型引数が引数から明らかである場合、省略できる
  • コンストラクタの型引数が引数から明らかであっても省略できない

型引数にジェネリクスのTを持つクラスがあるとします。

class MyClass<T> {
  public MyClass(T t) {
    this.Value = t;
  }
  public T Value { get; }
}

Tint型であることが明らかなので省略できる気がするが...

// コンパイルエラー
var c = new MyClass(10);

実際には型引数を省略することはできません。

以下のようにintを明示する必要があります。

var c = new MyClass<int>(10);

また、コレクション初期化子から型引数が明らかである場合も省略できません。

// `<string, int>`を省略できない
var dict = new Dictionary<string, int> {
  ["apple"] = 100,
  ["orange"] = 150,
  ["banana"] = 200
};

コンストラクタの型引数を省略するにはファクトリークラスを使う

メソッドは型引数が明らかである場合、省略することができます。

class MyClass<T> {
  public MyClass(T value) {
    this.Value = value;
  }
  public T Value { get; }
}

static class MyClassFactory {
  public static MyClass<T> New<T>(T value) => 
    new MyClass<T>(value);
}

以下の変数cMyClass<int>になります。

var c = MyClassFactory.New(10);

ファクトリークラスでインスタンスを生成することで型引数を省略することができました。

この方法はDictionary<TKey, TValue>のように型引数が多い型には時に有効です。

// Dictionary<TKey, TValue>のファクトリークラス
// クラス名を同じにするとそれっぽい(型引数あるなしでユーザー定義型として区別可能)
static class Dictionary {
  public static Dictionary<TKey, TValue> New<TKey, TValue>(
    params (TKey key, TValue value)[] tuples
  ) {
    var dict = new Dictionary<TKey, TValue>();
    foreach (var (key, value) in tuples) {
      dict.Add(key, value);
    }
    return dict;
  }
}

以下の変数dIDictionary<string, int>になります。

var d = Dictionary.New(
  ("apple", 100),
  ("orange", 150),
  ("banana", 200)
);

参考

なぜC#はクラスコンストラクタに暗黙のジェネリック型をサポートしていないのですか? - stackoverflow

16
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
10