Неявное преобразование из Nullable в normal, есть идеи?

#c# #nullable #implicit-conversion

#c# #nullable #неявное преобразование

Вопрос:

Я хочу получить представление о том, как неявно преобразовать nullable переменные «?» в окружные.

учитывая этот пример

 int? x = 5;

int y = x; //this gonna fail, !!!
  

мне нужен какой-то способ переопределить = parameter , но, к сожалению, параметр = нельзя перегрузить… есть предложения

Я использую C#

Комментарии:

1. На каком языке это? Или это не зависит от языка, и я не замечаю?

Ответ №1:

У вас есть два варианта: получить доступ к значению напрямую (если вы точно знаете, что оно не равно null):

 int y = x.Value;
  

или используйте оператор объединения null:

 int y = x ?? 0; // 0 if null...
  

Комментарии:

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

2. @Mustafa — если ты придумаешь, как сделать это неявно, дай мне знать 😉 В C # вы не можете перегружать оператор присваивания. Вы также не можете расширять int . То, как вы решите эту проблему, будет зависеть от архитектуры вашего приложения. Можете ли вы пойти другим путем и заменить все int s на int? s, поскольку int это неявно преобразует в int? ?

3. @Mustafa: Вы не можете переопределить оператор ‘=’, это не метод. Если бы вы сравнивали значения, используя .Equals метод, то вы могли бы написать переопределение для него.

4. вы правы, я не могу расширить ‘int’ и не могу перегрузить оператор =, я думаю, у меня нет другого выбора, кроме как перепроектировать модель предметной области для использования правильных типов данных, приветствия.

5. также int y = x.Имеет значение ? x.Value : 0; //0, если null

Ответ №2:

Можно реализовать неявный оператор приведения, но только к определяемым вами типам или из них. Например, сделать что-то вроде этого..

 public class NullableExtensions 
{
    public static implicit operator int(int? value)
    {
        return value ?? default(int);
    }
}
  

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

Самое близкое, что вы могли бы сделать, это определить свой собственный Nullable тип, который содержит неявный оператор приведения:

 public struct ImplicitNullable<T> where T: struct
{
    public bool HasValue { get { return this._value.HasValue; } }
    public T Value { get { return this._value.Value; } }

    public ImplicitNullable(T value) : this() { this._value = value; }
    public ImplicitNullable(Nullable<T> value) : this() { this._value = value; }

    public static implicit operator ImplicitNullable<T>(T value) { return new ImplicitNullable<T>(value); }
    public static implicit operator ImplicitNullable<T>(Nullable<T> value) { return new ImplicitNullable<T>(value); }

    public static implicit operator T(ImplicitNullable<T> value) { return value._value ?? default(T); }
    public static implicit operator Nullable<T>(ImplicitNullable<T> value) { return value._value; }

    private Nullable<T> _value { get; set; }

    // Should define other Nullable<T> members, especially 
    // Equals and GetHashCode to avoid boxing
}
  

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

После этого вы можете выполнять приведение туда и обратно, как ожидалось:

 static void Main()
{
    int myInt = 1;
    int? nullableInt = 2;

    ImplicitNullable<int> implicitInt;

    // Convert from int or int?
    implicitInt = myInt;
    implicitInt = nullableInt;

    // Convert to int or int?
    myInt = implicitInt;
    nullableInt = implicitInt;
}
  

Ответ №3:

Подождите, я так запутался…

Почему бы вам просто не использовать GetValueOrDefault?

Комментарии:

1. Потому что у меня уже есть написанный код, и я не хочу передавать его, набирая после каждого prop «GetValueOrDefault()», спасибо

Ответ №4:

Я предполагаю, что это C #.

Вам нужно либо привести, либо использовать .value :

  int? x = 5;
 int y;

 if(x.HasValue)
     y = x.Value;
 else
     throw new//... handle error or something