Как конвертировать C # обнуляемый int в int


484

Как я могу преобразовать обнуляемый intв int? Предположим, у меня есть 2 типа int, как показано ниже:

int? v1;  
int v2; 

Я хочу присвоить v1значение v2. v2 = v1;вызовет ошибку. Как мне конвертировать v1в v2?


Каково желаемое поведение, когда v1есть null?
Соломон Уцко

Ответы:


637

Все остальные ответы пока верны; Я просто хотел добавить еще один, который немного чище:

v2 = v1 ?? default(int);

Любой Nullable<T>является неявно конвертируемым к своему T, ПРЕДОСТАВЛЯЯ, что все вычисляемое выражение никогда не может привести к нулевому назначению ValueType. Таким образом, оператор с нулевым слиянием ??является просто синтаксическим сахаром для троичного оператора:

v2 = v1 == null ? default(int) : v1;

... который в свою очередь является синтаксическим сахаром для if / else:

if(v1==null)
   v2 = default(int);
else
   v2 = v1;

Кроме того, начиная с .NET 4.0, Nullable<T>есть метод «GetValueOrDefault ()», который является нулевым безопасным геттером, который в основном выполняет объединение нулей, как показано выше, так что это тоже работает:

v2 = v1.GetValueOrDefault();

4
Является ли на default(int)самом деле нужно? Что не так с простым 0?
Коул Джонсон

4
Это будет работать для этого примера, но в общем случае рекомендуется использовать defaultтам, где это необходимо. Ноль не всегда допустим в качестве значения, тем более, по умолчанию, поэтому, если вы замените intего универсальным, Tвы обнаружите, что мой код работает, а ноль - нет. В некоторых будущих версиях фреймворка defaultтакже может стать перегруженным; если и когда это произойдет, код, использующий default, будет легко использовать преимущества, в то время как явные нулевые или нулевые назначения должны быть изменены.
KeithS

5
Это должно подняться до вершины: .NET 4.0, Nullable <T> имеет «GetValueOrDefault ()»
RandomHandle

Спасибо, что вернулись, чтобы отредактировать его с помощью GetValueOrDefault!
CindyH

Вы можете быть осторожны с DateTime при использовании по умолчанию. Это может вставить дату по умолчанию вместо пустой.
Ранчо Камаль


92

Вы можете использовать свойство Value для назначения.

v2 = v1.Value;

8
Кроме того, если вы не уверены, содержит ли v1 значение null, вы можете использовать оператор объединения нулей, чтобы установить запасное значение. Например, v2 = v1 ?? 0;
Арьен

12
И обязательно проверьте v1.HasValueсначала.
Yuck

3
MSDN говорит, что это будет исключение, если v1есть null. На мой взгляд, это не правильный ответ.
ventiseis

6
@ventiseis Я думаю, что это желательное поведение - я удивлен, что многие другие ответы в порядке с тихим преобразованием нулевого в 0. Если вы присваиваете необнуляемый тип ненулевому типу, вы должны быть уверены, что значение на самом деле не равно нулю. ОП не сказал: «Я хочу назначить v1 для v2 или 0, если v1 равен нулю», но это, как все, казалось, предполагали
Майкл Мрозек


49

Если вы знаете, что v1имеет значение, вы можете использовать Valueсвойство:

v2 = v1.Value;

При использовании GetValueOrDefaultметода присваивается значение, если оно есть, в противном случае используется значение по умолчанию для типа или заданное вами значение по умолчанию:

v2 = v1.GetValueOrDefault(); // assigns zero if v1 has no value

v2 = v1.GetValueOrDefault(-1); // assigns -1 if v1 has no value

Вы можете использовать HasValueсвойство, чтобы проверить, v1имеет ли значение:

if (v1.HasValue) {
  v2 = v1.Value;
}

Существует также языковая поддержка GetValueOrDefault(T)метода:

v2 = v1 ?? -1;

Вы не должны использовать значение без предварительной проверки, чтобы увидеть, есть ли значение. Использовать ?? оператор вместо.
Питер


28

GetValueOrDefault()

получает значение объекта. Если это ноль, это возвращает значение по умолчанию int, которое является 0.

Пример:

v2= v1.GetValueOrDefault();


21

Если значение по умолчанию для данного типа является приемлемым результатом:

if (v1.HasValue)
    v2 = v1.GetValueOrDefault();

Если вам нужно другое значение по умолчанию, когда результат не определен:

v2 = v1.GetValueOrDefault(255);    // or any valid value for int in place of 255

Если вы просто хотите вернуть значение (независимо от того, произошел сбой или нет):

v2 = v1.GetValueOrDefault();


.NET 4.7.2 .: GetValueOrDefault()возвращает значение поля без какой-либо проверки.


15

Насколько мне известно, лучшим решением является использование GetValueOrDefault()метода.

v2 = v1.GetValueOrDefault();

этот был наиболее полезным для меня
Liakat


10

это возможно с v2 = Convert.ToInt32(v1);


Это будет работать технически, но другие методы, такие как HasValue / Value или GetValueOrDefault, работают намного эффективнее.
Брэндон Баркли


9

Простое преобразование между v1и v2невозможно, поскольку v1имеет большую область значений, чем v2. Это все v1может держать плюс nullсостояние. Для преобразования вам необходимо явно указать, какое значение intбудет использоваться для отображения nullсостояния. Самый простой способ сделать это - ??оператор

v2 = v1 ?? 0;  // maps null of v1 to 0

Это также может быть сделано в длинной форме

int v2;
if (v1.HasValue) {
  v2 = v1.Value;
} else {
  v2 = 0;
}

9

В зависимости от контекста использования вы можете использовать функцию сопоставления с образцом в C # 7:

int? v1 = 100;
if (v1 is int v2)
{
    Console.WriteLine($"I'm not nullable anymore: {v2}");
}

РЕДАКТИРОВАТЬ:

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

  • Сопоставление с образцом в C # 7 теперь позволяет нам проверять тип значения и приводить его неявно. В приведенном выше фрагменте условие if будет проходить только в том случае, если значение, хранимое в v1, совместимо с типом для типа for v2, которым в данном случае является int. Из этого следует, что когда значение для v1is null, условие if не будет выполнено, поскольку null не может быть назначен для int. Вернее, nullне является int.

  • Я хотел бы подчеркнуть, что это решение не всегда может быть оптимальным выбором. Как я предполагаю, я считаю, что это будет зависеть от точного контекста использования разработчика. Если у вас уже есть int?и вы хотите условно воздействовать на его значение, если-и-только-если назначенное значение не равно нулю (это единственный раз, когда безопасно преобразовать обнуляемое int в обычное int без потери информации), тогда сопоставление с образцом, пожалуй, один из самых кратких способов сделать это.


К сожалению, необходимо ввести новое имя переменной, но это лучшее (самое безопасное) решение, если нет значения по умолчанию, потому что нет риска случайного рефакторинга ваших HasValueчеков.
Minexew

Я просто не вижу никакого преимущества этого метода перед v1.HasValue в качестве проверки, а затем v1.Value для доступа к базовому значению. Я бы не стал опровергать это, но я думаю, что эта проблема уже решена, и новая методика не добавляет ясности этой проблеме. Я также оценил его на 8-9% медленнее.
Брэндон Баркли

Спасибо за сравнение, это приятно знать! В любом случае, если посмотреть, разница в лучшем случае незначительна (я полагаю, если вы не сделаете это в какой-то критически важной области). Я смотрю на это как на более "сжатое" или, возможно, "идиоматическое", поскольку оно опирается на синтаксические сахара, запеченные в языке вместо API. Это немного субъективно, но, возможно, это «более ремонтопригодно». Хотя на самом деле мне нравится этот подход больше, чем полагаться на значение по умолчанию, как предлагают многие другие ответы.
Николас Миллер

3

Это присвоит значение v1для v2если оно не равно нулю, в противном случае он будет принимать значения по умолчанию , как ноль.

v2=v1??0

Или ниже другой способ написать это.

v2 = v1.HasValue?v1:0


-1
 int v2= Int32.Parse(v1.ToString());

5
Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, почему и / или как этот код отвечает на вопрос, повышает его долгосрочную ценность.
Xiawi

1
Лучше использовать способ «лучшей практики», чтобы развернуть дополнительные функции, а не использовать закулисные трюки. См. Docs.microsoft.com/en-us/dotnet/csharp/language-reference/… для справки
lorg

При ответе на восьмилетний вопрос с пятнадцатью существующими ответами важно объяснить, каков новый аспект вопроса, к которому относится ваш ответ, и отметить, изменился ли ответ с течением времени. Код только ответы почти всегда можно улучшить, добавив некоторые объяснения.
Джейсон Аллер
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.