Возможно ли создание универсального метода C #, который принимает (обнуляемый) тип значения и ссылочный тип? - PullRequest
11 голосов
/ 23 октября 2010

Я хочу создать простой метод, который принимает как тип значения , так и тип ссылки параметры, то есть int является значением, а строка является ссылкой.

Итак, вот с чего я начал:

public bool areBothNotNull<T>(T? p1, T? p2)
{
    return (p1.HasValue && p2.HasValue);
}

Итак, я хочу использовать его следующим образом:

var r1 = areBothNotNull<int>(3, 4); // will be true
var r2 = areBothNotNull<int>(3, null); // will be false
var r3 = areBothNotNull<string>("three", "four"); // will be true
var r4 = areBothNotNull<string>(null, "four"); // will be false

Но первая проблема, с которой я столкнулсяis

Тип 'T' должен быть типом значения, не допускающим значения NULL, чтобы использовать его в качестве параметра 'T' в универсальном типе или методе 'System.Nullable'

Для продолжения Iдобавьте структурное ограничение к моему методу

public bool areBothNotNull<T>(T? p1, T? p2) where T : struct

Но теперь метод не принимает вызовы на основе строк и выдает мне такую ​​ошибку:

Тип 'string' должен быть необнуляемый тип значения, чтобы использовать его как параметр 'T' в универсальном типе или методе.

Возможно ли это?Или почему нам мешают это сделать?

1 Ответ

23 голосов
/ 23 октября 2010

Ваша проблема в том, что вы хотите, чтобы ограничения общего типа конфликтовали друг с другом:

  • Nullable<T> работает только с типами значений
  • Типы ссылок не являются типами значений

Так что для работы кода вам понадобятся две перегрузки:

public static bool areBothNotNull<T>(T? p1, T? p2) where T : struct
{            
    return (p1.HasValue && p2.HasValue);
}

public static bool areBothNotNull<T>(T p1, T p2)
{
    return (p1 != null && p2 != null);
}

Тем не менее, следующая строка никогда не будет компилироваться:

var r3 = areBothNotNull<string>(3, 4);

Здесь возникает конфликт, когда аргумент универсального типа утверждает, что параметры имеют тип string, но вместо этого код пытается передать int s.

...