모든 nullable에 대한 C # 제네릭 형식 제약 조건
그래서이 수업이 있습니다 :
public class Foo<T> where T : ???
{
private T item;
public bool IsNull()
{
return item == null;
}
}
이제 모든 것을 사용할 수있는 유형의 변수로 사용할 수있는 유형 제약 조건을 찾고 있습니다 null
. 즉, 모든 참조 유형과 모든 Nullable
( T?
) 유형을 의미합니다.
Foo<String> ... = ...
Foo<int?> ... = ...
가능해야합니다.
사용 class
유형 제약은 나를 참조 유형을 사용할 수 있습니다.
추가 정보 : 파이프 및 필터 애플리케이션을 작성 중이며 파이프 null
라인으로 전달되는 마지막 항목 으로 참조 를 사용하여 모든 필터가 멋지게 종료되고 정리 등을 수행 할 수 있도록 하고 싶습니다 .
타임 검사를하지 않고 Foo의 생성자에서 작동 검사를 수행하려는 경우 유형이 참조 또는 nullable 유형이 아닌지 확인하고 예외를 throw 할 수 있습니다.
작동 확인 만 허용하지 않을 수 있습니다.
public class Foo<T>
{
private T item;
public Foo()
{
var type = typeof(T);
if (Nullable.GetUnderlyingType(type) != null)
return;
if (type.IsClass)
return;
throw new InvalidOperationException("Type is not nullable or reference type.");
}
public bool IsNull()
{
return item == null;
}
}
그런 다음 다음 코드가 마지막 코드 ( foo3
)는 생성자에서 예외를 발생시킵니다.
var foo1 = new Foo<int?>();
Console.WriteLine(foo1.IsNull());
var foo2 = new Foo<string>();
Console.WriteLine(foo2.IsNull());
var foo3= new Foo<int>(); // THROWS
Console.WriteLine(foo3.IsNull());
제네릭 에서 OR 와 동등한 것을 구현하는 방법을 모르겠습니다 . 그러나 nullable 형식에는 null을 생성하는 구조에 0 값을 만들기 위해 기본 키워드 를 사용하도록 제안 할 수 있습니다 .
public class Foo<T>
{
private T item;
public bool IsNullOrDefault()
{
return Equals(item, default(T));
}
}
Nullable 버전을 구현할 수도 있습니다.
class MyNullable<T> where T : struct
{
public T Value { get; set; }
public static implicit operator T(MyNullable<T> value)
{
return value != null ? value.Value : default(T);
}
public static implicit operator MyNullable<T>(T value)
{
return new MyNullable<T> { Value = value };
}
}
class Foo<T> where T : class
{
public T Item { get; set; }
public bool IsNull()
{
return Item == null;
}
}
예 :
class Program
{
static void Main(string[] args)
{
Console.WriteLine(new Foo<MyNullable<int>>().IsNull()); // true
Console.WriteLine(new Foo<MyNullable<int>> {Item = 3}.IsNull()); // false
Console.WriteLine(new Foo<object>().IsNull()); // true
Console.WriteLine(new Foo<object> {Item = new object()}.IsNull()); // false
var foo5 = new Foo<MyNullable<int>>();
int integer = foo5.Item;
Console.WriteLine(integer); // 0
var foo6 = new Foo<MyNullable<double>>();
double real = foo6.Item;
Console.WriteLine(real); // 0
var foo7 = new Foo<MyNullable<double>>();
foo7.Item = null;
Console.WriteLine(foo7.Item); // 0
Console.WriteLine(foo7.IsNull()); // true
foo7.Item = 3.5;
Console.WriteLine(foo7.Item); // 3.5
Console.WriteLine(foo7.IsNull()); // false
// var foo5 = new Foo<int>(); // Not compile
}
}
"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()
입니다. 마지막으로 여기에 필요한 추가 코드는 특히 여러 개의 오버로드 된 생성자가 필요한 경우 증가합니다.
언급했듯이 컴파일 시간을 확인할 수 없습니다. .NET의 일반 제약 조건은 심각하게 부족하며 대부분의 시나리오를 지원하지 않습니다.
그러나 나는 이것이 런타임 검사를위한 더 나은 솔루션이라고 생각합니다. 둘 다 상수이기 때문에 JIT 컴파일 시간에 최적화 할 수 있습니다.
public class SomeClass<T>
{
public SomeClass()
{
// JIT-compile time check, so it doesn't even have to evaluate.
if (default(T) != null)
throw new InvalidOperationException("SomeClass<T> requires T to be a nullable type.");
T variable;
// This still won't compile
// variable = null;
// but because you know it's a nullable type, this works just fine
variable = default(T);
}
}
이러한 유형 제약은 불가능합니다. 형식 제약 에 대한 문서에 따르면 nullable 형식과 참조 형식을 모두 캡처하는 제약 조건이 없습니다. 제약은 결합으로 만 결합 될 수 있기 때문에 이러한 제약을 조합으로 만들 수있는 방법이 없습니다.
그러나 항상 == null을 확인할 수 있으므로 필요에 따라 unconstraint 형식 매개 변수로 대체 할 수 있습니다. 유형이 값 유형이면 검사는 항상 거짓으로 평가됩니다. 그런 다음 의미 체계가 적합한 한 R # 경고 "값 유형을 null과 비교할 수 있음"이 표시 될 수 있습니다. 이는 중요하지 않습니다.
대안은 다음을 사용할 수 있습니다.
object.Equals(value, default(T))
null 검사 대신 default (T) 여기서 T : class는 항상 null입니다. 그러나 이는 nullable이 아닌 값이 명시 적으로 설정되지 않았거나 기본값으로 설정된 경우 날씨를 구분할 수 없음을 의미합니다.
나는 사용한다
public class Foo<T> where T: struct
{
private T? item;
}
public class Foo<T>
{
private T item;
public Foo(T item)
{
this.item = item;
}
public bool IsNull()
{
return object.Equals(item, null);
}
}
var fooStruct = new Foo<int?>(3);
var b = fooStruct.IsNull();
var fooStruct1 = new Foo<int>(3);
b = fooStruct1.IsNull();
var fooStruct2 = new Foo<int?>(null);
b = fooStruct2.IsNull();
var fooStruct3 = new Foo<string>("qqq");
b = fooStruct3.IsNull();
var fooStruct4 = new Foo<string>(null);
b = fooStruct4.IsNull();
참고 URL : https://stackoverflow.com/questions/19831157/c-sharp-generic-type-constraint-for-everything-nullable
'IT' 카테고리의 다른 글
jQuery Validate- 그룹에서 하나 이상의 필드를 채워야합니다. (0) | 2020.08.22 |
---|---|
Youtube 비디오 소스를 HTML5 비디오 태그에 표시 하시겠습니까? (0) | 2020.08.22 |
Android Spinner에서 한 항목을 숨기는 방법 (0) | 2020.08.22 |
스트리밍 리소스가 RESTful 패러다임에 어떻게 처리합니까? (0) | 2020.08.22 |
이클립스에서 당신의 치료를 받으시나요? (0) | 2020.08.22 |