"nullable"(참조 유형 또는 Nullables)을 취할 수있는 일반적인 정적 메서드를 원하는 더 간단한 경우에 대해이 문제에 직면하여 만족스러운 솔루션없이이 질문을 받았습니다. 그래서 나는 두 개의 오버로드 된 메서드, 즉 a T
및 제약 조건이 where T : class
있고 다른 하나는 a T?
및 where T : struct
.
그런 다음 해당 솔루션을이 문제에 적용하여 생성자를 비공개 (또는 보호)하고 정적 팩토리 메서드를 사용하여 컴파일 타임에 확인할 수있는 솔루션을 만들 수도 있다는 것을 깨달았습니다.
//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);
}
}
이제 다음과 같이 사용할 수 있습니다.
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
매개 변수가없는 생성자를 원하면 오버로딩이 좋지는 않지만 다음과 같이 할 수 있습니다.
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?>();
}
}
다음과 같이 사용하십시오.
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
이 솔루션에는 몇 가지 단점이 있습니다. 하나는 객체를 구성하는 데 'new'를 사용하는 것을 선호 할 수 있다는 것입니다. 다른 하나는 Foo<T>
다음과 같은 유형 제약 조건에 대한 일반 유형 인수 로 사용할 수 없다는 것 where TFoo: new()
입니다. 마지막으로 여기에 필요한 추가 코드는 특히 여러 개의 오버로드 된 생성자가 필요한 경우 증가합니다.