2013-03-29 4 views
1

Я написал эту тривиальную функцию полезности:Generic функции типизированной: возвращает ненулевое значение

public static T isNull<T>(T? v, T d) 
{ 
    return v == null ? d : v.Value; 
} 

цель состоит в том, чтобы избежать раздражающей задачи, как проверка для члена, чтобы быть пустыми, очень распространены в чтении LinQ записей , Проблема заключается в том, что он бросает эту ошибку:

The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'System.Nullable< T>'

ошибка кажется законным, в любом случае я желаю я могу сделать что-то вроде этого:

int? myField = record.myField; 
int myValue = isNull(myField, 0); 

вместо:

int? myField = record.myField; 
int myValue = myField == null ? 0 : myField.Value; 

Я чувствую например, я пропускаю некоторые базовые знания C#. Существует ли способ выполнить мою задачу?

ответ

4

Это называется нулевой коалесцирующем, и есть встроенный оператор, чтобы сделать это:

int myValue = record.myField ?? 0 
+1

Для полноты: http://msdn.microsoft.com/en-us/library/ms173224.aspx –

+0

@LynnCrumbling Спасибо, это боль становится ссылки на телефон –

6

Generic constraints можно использовать на общих функций, чтобы ограничить типы, которые разрешено использовать для определенных подмножеств, и это открывает возможности для того, как вы могли бы использовать эти типы внутри метода или класса.

В этом случае вы можете применить ограничение к T, которое ограничивает его значением struct, чтобы решить вашу конкретную ошибку компилятора.

public static T IsNull<T>(T? v, T d) where T : struct 
{ 
    return v == null ? d : v.Value; 
} 

Однако другой ответ не правильно указать на то, что вы можете выбрать, чтобы использовать нулевой оператор коалесцирующего ?? в этом конкретной ситуации.

3

В то время как другие ответы хороши, вероятно, вы хотели бы написать свой метод так, что это будет работать с обоими ссылки и типы значений. Вы можете добиться этого, имея две перегрузки, как с общими ограничениями.

public static T IsNull<T>(T v, T d) where T : class 
{ 
    return v ?? d; 
} 

public static T IsNull<T>(T? v, T d) where T : struct 
{ 
    return v.HasValue ? v.Value : d; 
} 

Примечание: Вызов IsNull с типом значения, кроме Nullable<T> по-прежнему не компилируется. например

string myString = ... 
Console.WriteLine(IsNull(myString, "foo"))   // works 

object myObject = ... 
Console.WriteLine(IsNull(myMyObject, new object())) // works 

DateTime? myDateTime = ... 
Console.WriteLine(IsNull(myDateTme, DateTme.Now))  // works 

int? myInt1 = ... 
Console.WriteLine(IsNull(myInt1, DateTme.Now))  // works 

int myInt2 = ... 
Console.WriteLine(IsNull(myInt2, DateTme.Now))  // <-- compiler error