Як конвертувати 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він також може перезавантажуватися; якщо і коли це станеться, код, що використовує типовий, легко зможе скористатись, тоді як явні нульові чи нульові призначення повинні бути змінені.
КітС

5
Це має піднятися до вершини: .NET 4.0, Nullable <T> має "GetValueOrDefault ()"
RandomHandle

Дякуємо, що повернулися, щоб відредагувати його за допомогою GetValueOrDefault!
CindyH

Можливо, ви хочете бути обережними з DateTime, коли ви використовуєте за замовчуванням. Це може вставити дату за замовчуванням замість порожньої.
Ranch Camal


92

Ви можете використовувати властивість Value для призначення.

v2 = v1.Value;

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

12
І обов’язково спочатку перевірте v1.HasValue.
Юк

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()

отримує значення об’єкта. Якщо він є null, він повертає значення за замовчуванням 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();

цей найкращий для мене був корисний
Ляакат


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, сумісні з типом типу для v2, яким у цьому випадку є int. Звідси випливає , що , коли значення v1є 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.