コンストラクタの型引数が省略できるようでできない...
C#の型引数の省略
- メソッドの型引数が引数から明らかである場合、省略できる
- コンストラクタの型引数が引数から明らかであっても省略できない
型引数にジェネリクスのT
を持つクラスがあるとします。
class MyClass<T> {
public MyClass(T t) {
this.Value = t;
}
public T Value { get; }
}
T
はint
型であることが明らかなので省略できる気がするが...
// コンパイルエラー
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);
}
以下の変数c
はMyClass<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;
}
}
以下の変数d
はIDictionary<string, int>
になります。
var d = Dictionary.New(
("apple", 100),
("orange", 150),
("banana", 200)
);