Різниця між кастингом та використанням методу Convert.To ()


90

У мене є функція, яка відкидає значення doubleна stringзначення.

string variable = "5.00"; 

double varDouble = (double)variable;

Було зареєстровано зміну коду, і проект будується з помилкою: System.InvalidCastException: Specified cast is not valid.

Однак, виконавши наступне ...

string variable = "5.00"; 

double varDouble = Convert.ToDouble(variable);

... проект будується без помилок.

У чому різниця між кастингом та використанням Convert.To()методу? Чому кастинг кидає, Exceptionа використовує Convert.To()ні?

c#  casting 


6
Стосовно запитання , на яке посилається , ОП запитує, коли використовувати акторський склад або конвертувати, а прийнята відповідь говорить: "Це справді питання вибору, який би ви не використовували". Я прошу різницю між акторським складом і конвертом. На мою думку, відповіді нижче (слава ТО!) Надають більше деталей про відмінності в порівнянні з "використанням того чи іншого за вибором" ... і ця деталь може бути використана для поглибленого вибору, по суті.

@ edmastermind29 немає великої різниці між "яка різниця між x та y" та "коли використовувати x та y" у контексті програмування. Обидва взаємно відповідають іншому.
nawfal

2
Майже через 3 роки, схоже, в цьому випадку одне не відповідає іншому. Q: "Яка різниця між X та Y?" В: "Це справді питання вибору, яким би ти не користувався". Не дуже корисно.

Здається, ніхто не має прямої відповіді на те, який показник "Найкращий" - це також частина питання. З мого досвіду, я вважаю, Cast є кращим, особливо в отриманні таких значень стовпців. (Int) datatable.Rows [0] [0], якщо ми знаємо його 100% -ний інтерес
Sundara Prabu

Відповіді:


127

Навіть якщо ви можете бачити їх якось рівнозначними, вони абсолютно різні за призначенням. Спершу спробуємо визначити, що таке акторський склад:

Кастинг - це дія зміни об’єкта одного типу даних на інший.

Це трохи загально, і це якимось чином еквівалентно перетворенню, тому що привід часто має однаковий синтаксис перетворення, тому питання має полягати в тому, коли закидання (неявне чи явне) дозволено мовою, і коли потрібно використовувати ( більше) явне перетворення?

Дозвольте мені спочатку провести просту межу між ними. Формально (навіть якщо це еквівалентно для синтаксису мови) привід змінить тип, тоді як перетворення змінить / може змінити значення (з часом разом із типом). Також акторський склад є оборотним, тоді як конвертація може не бути.

Ця тема досить велика, тому спробуємо трохи звузити її, виключивши спеціальні оператори акторського складу з гри.

Неявний кидок

У C # привід є неявним, коли ви не втратите жодної інформації (зверніть увагу, що ця перевірка виконується з типами, а не з їх фактичними значеннями ).

Первісні типи

Наприклад:

int tinyInteger = 10;
long bigInteger = tinyInteger;

float tinyReal = 10.0f;
double bigReal = tinyReal;

Ці перекиди неявні, оскільки під час перетворення ви не втратите жодної інформації (ви просто робите тип ширшим). Навпаки, неявний прийом не дозволяється, оскільки, незалежно від їх фактичних значень (оскільки їх можна перевірити лише під час виконання), під час перетворення ви можете втратити деяку інформацію. Наприклад, цей код не компілюється, оскільки a doubleможе містити (і насправді це робить) значення, яке не можна представити за допомогою float:

// won't compile!
double bigReal = Double.MaxValue;
float tinyReal = bigReal;

Об'єкти

У випадку об'єкта (вказівник на) приведення завжди неявне, коли компілятор може бути впевнений, що тип джерела є похідним класом (або він реалізує) типом цільового класу, наприклад:

string text = "123";
IFormattable formattable = text;

NotSupportedException derivedException = new NotSupportedException();
Exception baseException = derivedException;

У цьому випадку компілятор знає, що stringреалізує, IFormattableа NotSupportedExceptionце (походить від), Exceptionтому приведення є неявним. Інформація не втрачається, оскільки об'єкти не змінюють своїх типів (це відрізняється від structs і примітивних типів, оскільки за допомогою прив'язки ви створюєте новий об'єкт іншого типу ), що змінює ваш погляд на них.

Відвертий привід

Привід явний, коли перетворювач не виконується неявно компілятором, і тоді ви повинні використовувати оператор приведення. Зазвичай це означає, що:

  • Ви можете втратити інформацію або дані, тому вам доведеться про це знати.
  • Перетворення може бути невдалим (оскільки ви не можете перетворити один тип на інший), тому знову ж таки, ви повинні бути в курсі того, що робите.

Первісні типи

Явний привід потрібен для примітивних типів, коли під час перетворення ви можете втратити деякі дані, наприклад:

double precise = Math.Cos(Math.PI * 1.23456) / Math.Sin(1.23456);
float coarse = (float)precise;

float epsilon = (float)Double.Epsilon;

В обох прикладах, навіть якщо значення потрапляють у floatдіапазон, ви втратите інформацію (в даному випадку точність), тому перетворення має бути явним. Тепер спробуйте це:

float max = (float)Double.MaxValue;

Це перетворення не вдасться, тому, знову ж таки, воно повинно бути явним, тому ви знаєте про це і можете зробити перевірку (у прикладі значення є постійним, але воно може надходити з деяких обчислень часу виконання або вводу-виводу). Повернімось до вашого прикладу:

// won't compile!
string text = "123";
double value = (double)text;

Це не компілюється, оскільки компілятор не може перетворити текст у числа. Текст може містити будь-які символи, не лише цифри, і це занадто багато, в C #, навіть для явного приведення (але це може бути дозволено іншою мовою).

Об'єкти

Перетворення з покажчиків (на об'єкти) можуть зазнати невдачі, якщо типи не пов'язані між собою, наприклад, цей код не компілюється (оскільки компілятор знає, що неможливе перетворення):

// won't compile!    
string text = (string)AppDomain.Current;
Exception exception = (Exception)"abc";

Цей код буде скомпільовано, але він може не вдатися під час виконання (це залежить від ефективного типу залитих об'єктів) із InvalidCastException:

object obj = GetNextObjectFromInput();
string text = (string)obj;

obj = GetNextObjectFromInput();
Exception exception = (Exception)obj;

Перетворення

Отже, нарешті, якщо касти - це перетворення, то навіщо нам потрібні такі класи Convert? Ігноруючи тонкі відмінності, що виникають від Convertреалізації та IConvertibleреалізацій, насправді тому, що в C # із складанням ви говорите компілятору:

повірте, цей тип - це той тип, навіть якщо ви зараз цього не можете знати, дозвольте мені це зробити, і ви побачите.

-або-

не хвилюйся, мені байдуже, що щось загубиться в цьому перетворенні.

Для всього іншого потрібна більш чітка операція (подумайте про наслідки легких приводів , тому C ++ ввів для них довгий, багатослівний та явний синтаксис). Це може включати складну операцію (для string-> doubleперетворення знадобиться синтаксичний розбір). Наприклад, перетворення на string, наприклад, завжди можливо (за допомогою ToString()методу), але це може означати щось інше, ніж те, що ви очікуєте, тому воно має бути більш явним, ніж акторський склад ( більше ви пишете, більше думаєте про те, що робите ).

Це перетворення можна виконати всередині об'єкта (використовуючи для цього відомі інструкції IL), використовуючи власні оператори перетворення (визначені в класі для приведення) або більш складні механізми (наприклад, TypeConverters або методи класу). Ви не знаєте, що станеться з цим, але ви знаєте, що це може провалитися (тому IMO, коли можливе більш контрольоване перетворення, ви повинні використовувати його). У вашому випадку перетворення просто проаналізує, stringщоб отримати double:

double value = Double.Parse(aStringVariable);

Звичайно, це може не вдатися, тому якщо ви це зробите, ви завжди повинні ловити виняток, який він може викинути ( FormatException). Тут це поза темою, але коли a TryParseє, тоді вам слід його використовувати (оскільки семантично ви говорите, що це не число, і це навіть швидше ... не вдається).

Перетворення в .NET можуть надходити з багатьох місць, TypeConverterнеявні / явні приведення з визначеними користувачем операторами перетворення, реалізація IConvertibleта методи синтаксичного аналізу (я щось забув?). Подивіться на MSDN, щоб дізнатися більше про них.

Щоб закінчити цю довгу відповідь, лише кілька слів про визначені користувачем оператори перетворення. Це просто цукор - дозволити програмісту використовувати гіпс для перетворення одного типу на інший. Це метод всередині класу (той, який буде відлитий), який говорить "привіт, якщо він / вона хоче перетворити цей тип на цей тип, я можу це зробити". Наприклад:

float? maybe = 10; // Equals to Nullable<float> maybe = 10;
float sure1 = (float)maybe; // With cast
float sure2 = maybe.Value; // Without cast

У цьому випадку це явно, оскільки воно може не вдатися, але це дозволено реалізації (навіть якщо про це є вказівки). Уявіть, що ви пишете власний клас рядків таким чином:

EasyString text = "123"; // Implicit from string
double value = (string)text; // Explicit to double

У своїй реалізації ви можете вирішити "полегшити життя програміста" і виставити цю конверсію за допомогою складання (пам'ятайте, це просто ярлик, щоб писати менше). Деякі мови можуть навіть дозволити таке:

double value = "123";

Дозволяє неявне перетворення в будь-який тип (перевірка буде виконуватися під час виконання). За допомогою відповідних параметрів це можна зробити, наприклад, у VB.NET. Це просто інша філософія.

Що я можу з ними робити?

Отже, останнє питання - коли слід користуватися тим чи іншим. Давайте подивимося, коли ви можете використовувати явний привід:

  • Перетворення між базовими типами.
  • Перетворення з objectна будь-який інший тип (сюди може входити і розпакування).
  • Перетворення з похідного класу в базовий клас (або в реалізований інтерфейс).
  • Перетворення з одного типу на інший за допомогою спеціальних операторів перетворення.

Тільки перша конверсія може бути виконана, Convertтому для інших у вас немає вибору, і вам потрібно використовувати явний привід.

Давайте подивимось зараз, коли ви можете використовувати Convert:

  • Перетворення з будь-якого базового типу на інший базовий тип (з деякими обмеженнями, див. MSDN ).
  • Перетворення з будь-якого типу, який реалізується, IConvertibleна будь-який інший (підтримуваний) тип.
  • Перетворення з / у byteмасив у / із рядка.

Висновки

ІМО Convertслід використовувати кожного разу, коли ви знаєте, що перетворення може бути невдалим (через формат, через діапазон або через те, що воно не підтримується), навіть якщо те саме перетворення можна виконати за допомогою приведення (якщо не доступне щось інше). Зрозуміло, хто буде читати ваш код, що ви маєте намір і що він може не вдатися (спрощення налагодження).

Для всього іншого вам потрібно використовувати гіпс, немає вибору, але якщо доступний інший кращий метод, то я пропоную вам використовувати його. У вашому прикладі перетворення з stringу double- це те, що (особливо якщо текст надходить від користувача) дуже часто не вдається, тому ви повинні зробити це якомога явнішим (крім того, ви отримуєте більше контролю над ним), наприклад, використовуючи TryParseметод.

Редагувати: яка різниця між ними?

Згідно з оновленим запитанням та збереженням того, що я писав раніше (про те, коли можна використовувати привід порівняно з тим, коли можна / доведеться використовувати Convert), останній пункт, який слід уточнити, полягає в тому, чи є між ними різниця (крім того, Convertвикористання IConvertibleта IFormattableінтерфейси, щоб він міг виконувати операції не дозволяється з акторським складом).

Коротка відповідь - так, вони поводяться по-різному . Я бачу Convertклас як клас допоміжних методів, тому часто він дає певні переваги або дещо іншу поведінку. Наприклад:

double real = 1.6;
int castedInteger = (int)real; // 1
int convertedInteger = Convert.ToInt32(real); // 2

Зовсім інакше, так? Актори зрізаються (це те, чого ми всі очікуємо), але Convertвиконує округлення до найближчого цілого числа (і цього може не сподіватися, якщо ви про це не знаєте). Кожен метод перетворення вводить відмінності, тому загальне правило не може бути застосовано, і їх слід розглядати в кожному конкретному випадку ... 19 базових типів для перетворення в будь-який інший тип ... список може бути досить довгим, набагато краще проконсультуватися у випадку MSDN за справа!


Я змінив питання , щоб запитати, Difference between casting and using the Convert.To() method. В іншому випадку дуже вичерпна відповідь. (Сподіваюся, моє запитання знову відкрито ...)

@ edmastermind29 Я трохи відредагував питання, тема задовга навіть для довгої відповіді (300+ можливих перетворень у списку). Конвертування додає переваги (або просто несподівану поведінку?) Не тільки проти приводів, але і проти "простих" інтерфейсів IConvertible та IFormattable.
Адріано Репетті

Мені не подобається поняття, запозичене у C, що doubleзначення, які не представляють цілих чисел, повинні бути "конвертованими" int. Кидок , здавалося б , відповідну парадигму в тих випадках , коли , наприклад , один вилучення Int32значень з double[]яких має поєднання дійсних чисел і Int32значень , які були перетворені в double[спробі перетворити значення, яка не подана саме в int32вказувало б несподіване умова і повинен викликати виняток], але я думаю, що коли хтось хоче перетворення з втратами, він повинен бути конкретним щодо форми, яку хоче.
supercat

1
Інша відмінність - від об’єктних до примітивних типів. напр.object o = 123; var l = Convert.ToInt64(o); var i = (long) (int) o; var f = (long) o // InvalidCastException
юе ши

1
@ rory.ap це важливий момент. Ні, формально це не кидок ( float-> int), а примус . Акторський склад може бути, наприклад DerivedClass-> BaseClass. Це бентежить, тому що в C # ми використовуємо одне і те ж слово (і оператор) для обох, але насправді це різні речі. Формальне визначення для розрізнення між ними дещо складніше, ніж те, що я писав.
Адріано Репетті

12

Кастинг - це спосіб сказати компілятору: "Я знаю, що ти думаєш, що ця змінна є Bar, але я знаю більше, ніж ти; об'єкт насправді Foo, тому дозвольте мені поводитися з ним так, ніби це Foo з зараз." Потім, під час виконання, якщо фактичний об’єкт виявився справді Foo, тоді ваш код працює, якщо виявиться, що об’єкт взагалі не був Foo, то ви отримаєте виняток. (Зокрема System.InvalidCastException.)

З іншого боку, перетворення - це спосіб сказати: "Якщо ви дасте мені об'єкт типу Bar, я можу створити абсолютно новий об'єкт Foo, який представляє те, що знаходиться в цьому об'єкті Bar. Я не буду змінювати оригінальний об'єкт, він виграв" т розглядати вихідний об'єкт по- різному, це буде що - щось нове , що тільки грунтуючись на який - небудь інший вартості . про те , як це зробити, це може бути що завгодно. в разі Convert.ToDoubleцього буде в кінцевому підсумку викликуDouble.Parseякий має всіляку складну логіку для визначення того, які типи рядків представляють, які числові значення. Ви можете написати свій власний метод перетворення, який відображає рядки вдвічі по-різному (можливо, для підтримки якогось зовсім іншого правила відображення чисел, таких як римські цифри чи інше). Перетворення може зробити що завгодно, але ідея полягає в тому, що ви насправді не просите компілятор щось зробити за вас; саме ви пишете код, щоб визначити, як створити новий об’єкт, оскільки компілятор без вашої допомоги не може знати, як зіставити (як приклад) a stringз a double.

Отже, коли ви конвертуєте, а коли робите? В обох випадках ми маємо деяку змінну типу, скажімо A, і ми хочемо мати змінну типу B. Якщо наш об'єкт A дійсно, насправді, під капотом, є B, тоді ми робимо актор. Якщо це насправді не B, тоді нам потрібно перетворити його і визначити, як програма повинна отримувати B з A.


В одному з публікацій SO Ерік Ліпперт згадав, що не існує такого поняття, що називається неявним складом, і це неявне перетворення . Я використовую актори і конверсію як взаємозамінні. що поганого у вимові "неявного складання"? Хіба якщо перетворення є неявним, не вимагаючи жодного складання, можна сказати, що це "неявний привід"?
rahulaga_dev

1
@RahulAgarwal Що таке приведення - це операція, в якій вам потрібно чітко вказати, що даний тип є (або може бути зроблений) дійсним екземпляром іншого типу. Коли існує неявна конверсія, не потрібен привід для обробки типу як іншого типу привід. Отже, сказати "неявний привід" насправді не має сенсу (за винятком тих небагатьох ситуацій, як Ерік, про які згадував Ерик, коли оператор приведення додається без того, щоб розробник його вводив, як при використанні a foreach). Поза цими винятками, акторські склади за визначенням явні.
Серві 20.03.18

5

Від MSDN:

Явні перетворення (приведення): Для явних перетворень потрібен оператор приведення. Кастинг потрібен, коли інформація може бути втрачена під час перетворення або коли перетворення може не вдатися з інших причин. Типові приклади включають числове перетворення в тип, який має меншу точність або менший діапазон, і перетворення екземпляра базового класу в похідний клас.

Розглянемо наступний приклад:

double a = 2548.3;
int b;
b = (int)a; //2548 --> information (.3) lost in the conversion

А також:

Акторський склад - це спосіб явного інформування компілятора про те, що ви збираєтеся здійснити перетворення, і що ви знаєте, що може статися втрата даних.

Ви можете використовувати System.Convertклас, коли хочете конвертувати між несумісними типами. Основна відмінність між литтям і зверненим є компіляції і час виконання . Винятки з перетворення типів з'являються під час виконання , тобто приведення типу, яке не вдається під час виконання, призведе InvalidCastExceptionдо кидання.


Висновок: Під час кастингу ви повідомляєте компілятору, що aце справді тип, bі якщо так, проект будується без помилок, як у цьому прикладі:

double s = 2;
int a = (int) s;

Але при перетворенні, про яке ви говорите компілятору, є спосіб створити новий об'єкт з a типу b, будь ласка, зробіть це, і збірки проекту без помилок, але, як я вже говорив, якщо приведення типу не вдається виконати, це призведе InvalidCastExceptionдо бути кинутим .

Наприклад, наведений нижче код ніколи не компілюється, оскільки компілятор виявляє, що не може передавати вираз типу DateTime передати типу int:

DateTime s = DateTime.Now;
int a = (int)(s);

Але цей складений успішно:

DateTime s = DateTime.Now;
int a = Convert.ToInt32(s);

Але під час виконання ви отримаєте, InvalidCastExceptionщо говорить:

Недійсний приклад із "DateTime" на "Int32".


4

Convert.DoubleМетод на насправді просто внутрішньо викликає Double.Parse(string)метод.

Ні Stringтип, ні Doubleтип не визначають явне / неявне перетворення між двома типами, тому кастинг завжди буде невдалим.

Double.ParseМетод буде дивитися на кожен символ в stringі побудувати числове значення , засноване на значеннях символів в string. Якщо будь-який із символів недійсний, Parseметод не працює (що також призводить Convert.Doubleдо невдачі методу).


1
І чим це відрізняється від явного акторського складу?

3
Явний привід не розглядає тип даних, а лише байти. Прикладом може бути приведення char x = '1' до цілого числа, ціле число буде 49, оскільки символ '1' є # 49 у таблиці ascii
user1751547

@ user1751547 Отже, чи не Convert.ToDouble()подивиться користувач байтів і розгляне дані?

@ user1751547 Я думаю, що саме така інтуїція потрібна для правильної відповіді на це питання. Просто сказати "це не визначено" - це трохи спірне питання.
Ant P

@ edmastermind29 Так, він буде дивитись на тип введення, і якщо це буде рядок, він буде проходити через кожен символ, знаючи, що якщо значення ascii символу char дорівнює 49, то це символ "1" і перетворює його належним чином
user1751547

3

У вашому прикладі ви намагаєтеся привести рядок до подвійного (не інтегрального типу).

Для його роботи потрібне явне перетворення.

І я повинен зазначити, що ви могли б використовувати Convert.ToDoubleзамість цього, Convert.ToInt64оскільки ви можете втратити дробові частини подвійного значення при перетворенні в int.

якщо ваша змінна має значення "5,25", varDouble становив би 5,00 (втрата 0,25 через перетворення в Int64)

Щоб відповісти на ваше запитання про кастинг і конвертацію.

Ваш акторський склад (явний акторський склад) не відповідає вимогам до явного акторського складу. значення, яке ви намагаєтесь надати за допомогою оператора приведення, є недійсним (тобто не інтегральним).

Відвідайте цю сторінку MSDN, щоб ознайомитися з правилами кастингу / конверсії


@ edmastermind29 я оновив свою відповідь. сподіваюся, це відповідає на ваше запитання.
Scartag

Які вимоги до явного акторського складу ... стосовно мого запитання? Це стосовно "не інтегрального" значення?

@ edmastermind29 Так. якщо значення, яке ви намагаєтесь привести до числового типу, є нечисловим, приведення недійсне .. необхідне перетворення.
scartag

3

Кастинг не передбачає жодного перетворення, тобто внутрішнє представлення значення не змінюється. Приклад:

object o = "Hello"; // o is typed as object and contains a string.
string s = (string)o; // This works only if o really contains a string or null.

Ви можете перетворити a doubleна stringподібне

double d = 5;
string s = d.ToString(); // -> "5"

// Or by specifying a format
string formatted = d.ToString("N2"); // -> "5.00"

Перетворити a stringв a можна doubleкількома способами (тут лише два з них):

string s = "5";
double d = Double.Parse(s); // Throws an exception if s does not contain a valid number

Або безпечним способом

string s = "5";
double d;
if (Double.TryParse(s, out d)) {
    Console.WriteLine("OK. Result = {0}", d);
} else {
    Console.WriteLine("oops!");
}

Convert.ToDouble()внутрішні дзвінкиDouble.Parse() . Це мені вигідно використовувати Convert.ToDouble()над Double.Parse()чи ні і чому?

Convert.ToDoubleмає багато перевантажень, які приймають різні типи вхідних даних. Прийом перевантаження stringповертається, 0.0якщо nullпередано рядок. Окрім цього, я не бачу переваг у його використанні.
Олів'є Жако-Декомб

Отже, або ... або Double.Parse()має щось запропонувати, що я повинен розглянути?

Double.Parse()є більш прямим, ніж Convert.ToDouble(). Якщо ви впевнені, що ваш рядок міститиме дійсний номер, ви можете сміливо використовувати його, інакше я раджу вам використовувати Double.TryParse.
Олів'є Жако-Декомб

1
string variable = "5.00";     
double varDouble = (double)variable;

Вище перетворення просто не дозволяється мовою. Ось список явних приводів для числових типів: http://msdn.microsoft.com/en-us/library/yht2cx7b.aspx Як бачите, навіть не кожен числовий тип можна перетворити на інший числовий тип

Детальніше про кастинг тут

І чим це відрізняється від Convert.ToDouble ()?

Коли ви приводите тип, структура даних не змінюється. Ну, у разі перетворення числових значень ви можете втратити кілька бітів або отримати кілька додаткових 0 бітів. Але ви все ще працюєте з номером. Ви просто змінюєте обсяг пам'яті, зайнятий цим числом. Це досить безпечно, щоб компілятор зробив усе необхідне.

Але коли ви намагаєтесь привести рядок до числа, ви не можете цього зробити, оскільки недостатньо змінити обсяг пам'яті, зайнятий змінною. Наприклад, 5.00оскільки рядок є послідовністю "чисел": 53 (5) 46 (.) 48 (0) 48 (0) - тобто для ASCII, але рядок міститиме щось подібне. Якщо компілятор просто візьме перші N (4 для подвійних? Не впевнений) байт з рядка - ця частина буде містити зовсім інше подвійне число. Одночасно Convert.ToDouble () запускає спеціальний алгоритм, який прийме кожен символ рядка, з’ясує цифру, яку він представляє, і зробить вам подвійне число, якщо рядок представляє число. Такі мови, як PHP, грубо кажучи, викликатимуть Convert.ToDouble для вас у фоновому режимі. Але C #, як і статично набрана мова, не зробить цього за вас. Це дозволяє вам бути впевненим, що будь-яка операція безпечна для типу, і ви не отримаєте чогось несподіваного, роблячи щось на зразок:

double d = (double)"zzzz"

@ edmastermind29 див. мою оновлену відповідь. Я намагався це пояснити. Пояснення далеко не ідеальне, але припустимо, воно пояснює різницю.
Viktor S.

1

Трансляція рядка до подвійного типу не дозволяється C #, тому ви отримуєте виняток, вам потрібно перетворити рядок ( документ MSDN, який показує прийнятні шляхи перетворення). Це просто тому, що рядок не обов’язково міститиме числові дані, але різні числові типи будуть (забороняючи нульові значення). A Convertзапустить метод, який перевірить рядок, чи можна його перетворити на числове значення. Якщо це можливо, він поверне це значення. Якщо не вдасться, це викличе виняток.

Щоб перетворити його, у вас є кілька варіантів. Ви використовували Convertметод у своєму питанні, є такий, Parseякий багато в чому схожий на Convert, але ви також повинні подивитися на TryParse, який дозволить вам зробити:

string variable = "5.00"; 

double varDouble;

if (Double.TryParse(variable, out varDouble)) {
    //Code that runs if the conversion succeeded.
} else {
    //Code that runs if the conversion failed.
}

Це дозволяє уникнути можливого винятку, якщо ви спробуєте Convertабо Parseне числовий рядок.


Чи вигідно мені використовувати TryParseнадмір, Convertтому що TryParseперевіряє, чи перетворення вдалося?

@ edmastermind29 Я думаю, що так. Перетворення призведе до винятку, якщо перетворення не вдається. TryParse поверне логічне значення True, якщо перетворення вдалося, і False, якщо воно не вдалося.
Кін

1

double varDouble = (double)variableприпускає, що variableце вже дубль. Якщо variableце не дубль (це рядок), це не вдасться. double varDouble = Convert.ToDouble(variable)робить так, як сказано - перетворює. Якщо він може проаналізувати або іншим чином витягнути подвійне, variableтоді це буде.

Я використовую друге, Double.Parseабо Double.TryParseтому, що воно чіткіше вказує на те, що має відбуватися. Ви починаєте з рядка і очікуєте, що він буде конвертованим у подвійний. Якщо є якісь сумніви, використовуйте TryParse.

Якщо variableаргумент методу, змініть тип на double. Покладіть на абонента відповідальність за надання правильного типу. Таким чином компілятор виконує роботу за вас.


-1

Найголовніша відмінність полягає в тому, що якщо використовується приведення типу , а перетворення не вдається (скажімо, ми перетворюємо дуже велике значення з плаваючою величиною в int), жоден виняток не буде видано, і буде показано мінімальне значення, яке може містити int. Але у випадку використання Convert для таких сценаріїв буде створено виняток.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.