Как проверить, вызывается ли функция generi c с аргументом обнуляемого generi c - PullRequest
0 голосов
/ 19 января 2020

Я пытаюсь написать обобщенную функцию c, которая ведет себя по-разному в зависимости от того, была ли она вызвана с аргументом, который допускает нулевые значения или нет. В мире до C # 8 я использовал что-то вроде этого:

T MyFunc<T>()
{
  object value = SomeExternalFunctionCall();
  if (value == null)
  {
    if (typeof(T).AcceptsNulls())
    {
      return null;
    }
    else
    {
      throw new Exception($"{typeof(T).Name} does not support nulls");
    }
  }
  return (T)value;
}

Где AcceptsNulls() было так:

public static bool IsAcceptNulls(this Type type)
{
  if (type.IsValueType)
  {
    if (Nullable.GetUnderlyingType(type) != null)
    {
      return true;
    }
    return false;
  }
  return true;
}

Так что MyFunc работал хорошо как для справки, так и для справки. типы значений, с надлежащей поддержкой для типов значений, допускающих значение NULL.

Но теперь я хочу иметь его в коде с поддержкой значений NULL. И я бы хотел, чтобы он мог различать guish MyFunc<object>() и MyFunc<object?>() случаев, поэтому он будет выдавать при обработке нулевого значения в первом случае, но не во втором.

Понятно, что я не могу проверить это с помощью проверки типа, поскольку обнуляемость ссылочного типа является функцией времени компиляции.

Как я могу это сделать? Это вообще возможно?


Обновление

Похоже, мое намерение неясно, поэтому я бы go уточнил детали.

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

Со структурами, допускающими обнуление, он работает просто отлично:


int noNullsForThisVariable = MyFunc<int>();

int? nullsAreOkHere = MyFunc<int?>();

Я хочу обеспечить такое же поведение для ссылочных типов сейчас.

Ответы [ 2 ]

2 голосов
/ 20 января 2020

Возможно, имеется недоразумение.

Необнуляемые ссылочные типы, например, строка (вместо строки?), Существуют только во время разработки. Во время выполнения строка имеет значение NULL, независимо от того, написали ли вы строку вместо строки? После уточнения вопроса можно ответить на этот вопрос. С точки зрения обнуляемости ничего не изменилось с c# 8.

1 голос
/ 23 января 2020

Позвольте мне объяснить, почему ваш подход вообще невозможен для ссылочных типов. (по крайней мере, до c# 8. это поведение может измениться в будущих c# версиях)

Поскольку ссылочные типы всегда допускают обнуление во время выполнения, в самом типе нет различий.

возможно, поэтому вы не можете сделать это: typeof (строка?). Вы получите сообщение об ошибке типа: "typeof не может использоваться для ссылочных типов, допускающих обнуляемость"

Но это не так обязательно означает, что компиляция не добавляет различимый атрибут или что-то подобное. (что действительно может быть)

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

Проверьте это самостоятельно с помощью следующего кода.

    string nonNullableString = "3434";
    string? nullableString = "3434";

    var nnStringType = nonNullableString.GetType();
    var stringType = nullableString.GetType();

    var isEqual = nnStringType == stringType; // true
    if(object.ReferenceEquals(nnStringType, stringType)) // true
        Debug.Print("it's the same object");

Обнуляемая и не обнуляемая строка одного типа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...