"Nullable" (referans türleri veya Nullable'lar) alabilen genel bir statik yöntem isteyen daha basit bir durum için bu sorunla karşılaştım, bu da beni tatmin edici bir çözüm olmadan bu soruya getirdi. Bu yüzden, basitçe iki aşırı yüklenmiş yönteme sahip olarak çözülmesi OP'nin belirttiği sorudan nispeten daha kolay olan kendi çözümümü buldum, biri a alan T
ve kısıtlamaya sahip, where T : class
diğeri a T?
ve sahip olan where T : struct
.
Daha sonra, kurucuyu özel (veya korumalı) yaparak ve statik bir fabrika yöntemi kullanarak derleme zamanında kontrol edilebilen bir çözüm oluşturmak için çözümün bu soruna da uygulanabileceğini fark ettim:
//this class is to avoid having to supply generic type arguments
//to the static factory call (see CA1000)
public static class Foo
{
public static Foo<TFoo> Create<TFoo>(TFoo value)
where TFoo : class
{
return Foo<TFoo>.Create(value);
}
public static Foo<TFoo?> Create<TFoo>(TFoo? value)
where TFoo : struct
{
return Foo<TFoo?>.Create(value);
}
}
public class Foo<T>
{
private T item;
private Foo(T value)
{
item = value;
}
public bool IsNull()
{
return item == null;
}
internal static Foo<TFoo> Create<TFoo>(TFoo value)
where TFoo : class
{
return new Foo<TFoo>(value);
}
internal static Foo<TFoo?> Create<TFoo>(TFoo? value)
where TFoo : struct
{
return new Foo<TFoo?>(value);
}
}
Şimdi bunu şu şekilde kullanabiliriz:
var foo1 = new Foo<int>(1); //does not compile
var foo2 = Foo.Create(2); //does not compile
var foo3 = Foo.Create(""); //compiles
var foo4 = Foo.Create(new object()); //compiles
var foo5 = Foo.Create((int?)5); //compiles
Parametresiz bir kurucu istiyorsanız, aşırı yükleme nezaketini elde edemezsiniz, ancak yine de şöyle bir şey yapabilirsiniz:
public static class Foo
{
public static Foo<TFoo> Create<TFoo>()
where TFoo : class
{
return Foo<TFoo>.Create<TFoo>();
}
public static Foo<TFoo?> CreateNullable<TFoo>()
where TFoo : struct
{
return Foo<TFoo?>.CreateNullable<TFoo>();
}
}
public class Foo<T>
{
private T item;
private Foo()
{
}
public bool IsNull()
{
return item == null;
}
internal static Foo<TFoo> Create<TFoo>()
where TFoo : class
{
return new Foo<TFoo>();
}
internal static Foo<TFoo?> CreateNullable<TFoo>()
where TFoo : struct
{
return new Foo<TFoo?>();
}
}
Ve bunu şu şekilde kullanın:
var foo1 = new Foo<int>(); //does not compile
var foo2 = Foo.Create<int>(); //does not compile
var foo3 = Foo.Create<string>(); //compiles
var foo4 = Foo.Create<object>(); //compiles
var foo5 = Foo.CreateNullable<int>(); //compiles
Bu çözümün birkaç dezavantajı vardır, bunlardan biri, nesneleri oluşturmak için 'yeni'yi kullanmayı tercih edebilirsiniz. Başka Kullanmak mümkün olmayacak olmasıdır Foo<T>
gibi bir şey bir tür kısıtlaması için genel tür bağımsız değişken olarak: where TFoo: new()
. Son olarak, burada ihtiyacınız olan ve özellikle birden fazla aşırı yüklenmiş kurucuya ihtiyacınız varsa artacak olan fazladan kod bitidir.