Dönüştürme ile Convert.To () yöntemini kullanma arasındaki fark


91

Bir atmalarını bir işlevi var doubleüzerinde stringdeğerler.

string variable = "5.00"; 

double varDouble = (double)variable;

Bir kod değişikliği kontrol edildi ve proje şu hatayla oluşturuldu: System.InvalidCastException: Specified cast is not valid.

Ancak, aşağıdakileri yaptıktan sonra ...

string variable = "5.00"; 

double varDouble = Convert.ToDouble(variable);

... proje herhangi bir hata olmadan oluşturulur.

Döküm ve Convert.To()yöntemi kullanmak arasındaki fark nedir ? Neden atmak bir atıyor Exceptionve kullanmıyor Convert.To()?

c#  casting 

sesler
şuna

6
Başvurulan bir soru ile ilgili olarak , OP ne zaman cast veya dönüştürme kullanılacağını sorar ve kabul edilen yanıt "Hangisini kullanırsanız kullanın gerçekten bir seçim meselesidir" der. Oyuncu ile dönüştüren arasındaki farkı soruyorum. Bana göre, aşağıdaki cevaplar (tebrikler SO!), "Bunu veya bunu seçerek" arasındaki farklar hakkında daha fazla ayrıntı sağlıyor ... ve bu ayrıntı, özünde daha bilinçli bir seçim yapmak için kullanılabilir.

@ edmastermind29 programlama bağlamında "x ve y arasındaki fark nedir" ve "x ve y ne zaman kullanılmalı" arasında çok fazla fark yoktur. Her ikisi de karşılıklı olarak diğerine cevap verir.
nawfal

2
Yaklaşık 3 yıl sonra, bu durumda birinin diğerini karşılıklı olarak yanıtladığı görülmüyor. S: "X ve Y arasındaki fark nedir?" C: "Hangisini kullanırsanız kullanın gerçekten bir seçim meselesi." Pek kullanışlı değil.

Hiç kimse, en iyi performansın da sorunun bir parçası olduğu konusunda doğrudan bir cevaba sahip görünmüyor, Deneyimlerime göre, Cast'ın özellikle bu gibi sütun değerlerini elde etmede daha iyi olduğunu görüyorum .. (int) datatable.Rows [0] [0], eğer % 100 int
Sundara Prabu

Yanıtlar:


127

Eğer bile olabilir onları görmek nasılsa eşdeğer olarak onlar amaç tamamen farklı. Önce bir oyuncu kadrosunun ne olduğunu tanımlamaya çalışalım:

Çevrim, bir veri türündeki bir varlığı diğerine değiştirme eylemidir.

Bu biraz geneldir ve bir şekilde bir dönüşüme eşdeğerdir, çünkü bir oyuncu genellikle aynı dönüşüm sözdizimine sahiptir, bu nedenle soru , dil tarafından bir döküm (örtük veya açık) izin verildiğinde ve ne zaman a ( daha fazla) açık dönüşüm?

Önce aralarına basit bir çizgi çizeyim . Resmi olarak (dil sözdizimi için eşdeğer olsa bile), bir dönüşüm türü değiştirirken bir dönüşüm değeri değiştirir / değiştirebilir (sonunda türle birlikte ). Ayrıca bir dönüştürme tersine çevrilebilirken bir dönüşüm olmayabilir.

Bu konu oldukça geniş, bu yüzden özel cast operatörlerini oyundan çıkararak biraz daraltmaya çalışalım.

Örtülü yayınlar

C # 'da herhangi bir bilgiyi kaybetmediğinizde bir çevrim örtüktür (lütfen bu denetimin gerçek değerleriyle değil türlerle yapıldığını unutmayın ).

İlkel türler

Örneğin:

int tinyInteger = 10;
long bigInteger = tinyInteger;

float tinyReal = 10.0f;
double bigReal = tinyReal;

Bu türler örtüktür çünkü dönüştürme sırasında herhangi bir bilgiyi kaybetmezsiniz (sadece türü genişletirsiniz). Bunun tersi örtük atama izin verilmez çünkü gerçek değerlerine bakılmaksızın (çünkü bunlar yalnızca çalışma zamanında kontrol edilebilirler) dönüştürme sırasında bazı bilgileri kaybedebilirsiniz. Örneğin, bu kod derlenmez çünkü a double, a ile temsil edilemeyen bir değer içerebilir (ve aslında içerir) float:

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

Nesneler

Bir nesne olması durumunda (bir işaretçi), derleyici kaynak türünün türetilmiş bir sınıf olduğundan (veya hedef sınıfın türünü uyguladığından) emin olabildiğinde çevrim her zaman örtüktür, örneğin:

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

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

Bu durumda derleyici bilir o stringuygular IFormattableve o NotSupportedException(türetilmiştir) 'dir Exceptiondökme örtülü yani. Nesneler türlerini değiştirmediği için hiçbir bilgi kaybolmaz (bu, structs ve ilkel türlerde farklıdır çünkü bir döküm ile başka türden yeni bir nesne yaratırsınız ), sizin onlara bakışınız ne değişir .

Açık yayınlar

Dönüştürme, derleyici tarafından dolaylı olarak yapılmadığında ve daha sonra cast operatörünü kullanmanız gerektiğinde, bir dönüştürme açıktır. Genellikle şu anlama gelir:

  • Bilgi veya verileri kaybedebilirsiniz, bu yüzden bunların farkında olmanız gerekir.
  • Dönüştürme başarısız olabilir (çünkü bir türü diğerine dönüştüremezsiniz) bu nedenle, yine, ne yaptığınızın farkında olmalısınız.

İlkel türler

İlkel türler için, dönüştürme sırasında bazı verileri kaybedebileceğiniz durumlarda, örneğin:

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

float epsilon = (float)Double.Epsilon;

Her iki örnekte de, değerler floataralık dahilinde olsa bile bilgileri kaybedersiniz (bu durumda hassasiyet), bu nedenle dönüşümün açık olması gerekir. Şimdi şunu dene:

float max = (float)Double.MaxValue;

Bu dönüşüm başarısız olacaktır, bu nedenle, bunun farkında olmanız için açık olmalıdır ve bir kontrol yapabilirsiniz (örnekte değer sabittir, ancak bazı çalışma zamanı hesaplamalarından veya G / Ç'den gelebilir). Örneğinize geri dönelim:

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

Derleyici metni sayılara dönüştüremediğinden bu derlenmez. Metin yalnızca sayıları değil, herhangi bir karakteri içerebilir ve bu, C # dilinde, açık bir tür için bile çok fazladır (ancak başka bir dilde izin verilebilir).

Nesneler

İşaretçilerden (nesnelere) dönüşümler, türler ilgisiz ise başarısız olabilir, örneğin bu kod derlenmez (çünkü derleyici olası bir dönüşüm olmadığını bilir):

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

Bu kod derlenir, ancak çalışma zamanında başarısız olabilir (etkili dönüştürülen nesnelerin türüne bağlıdır) bir InvalidCastException:

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

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

Dönüşümler

Son olarak, eğer yayınlar dönüşüm ise, o zaman neden gibi sınıflara ihtiyacımız var Convert? Gerçekleştirme Convertve IConvertibleuygulamalardan kaynaklanan ince farklılıkları görmezden gelmek, çünkü C # 'da derleyiciye şunu söylüyorsunuz:

güven bana, bu tip bu tip, şimdi bilmesen bile, bırak ben yapayım, göreceksin.

-veya-

Endişelenme, bu dönüşümde bir şeyin kaybolup kaybolmayacağı umurumda değil.

Diğer her şey için daha açık bir işleme ihtiyaç vardır ( kolay yayınların çıkarımlarını düşünün , bu yüzden C ++ onlar için uzun, ayrıntılı ve açık sözdizimi sundu). Bu, karmaşık bir işlemi içerebilir ( string-> doubledönüştürme için bir ayrıştırma gerekli olacaktır). stringÖrneğin, bir dönüştürme her zaman mümkündür ( ToString()yöntem yoluyla ) ancak beklediğinizden farklı bir şey ifade edebilir, bu nedenle bir oyuncu kadrosundan daha açık olmalıdır (ne kadar çok yazarsanız, ne yaptığınızı daha çok düşünürsünüz ).

Bu dönüştürme, nesnenin içinde (bunun için bilinen IL talimatları kullanılarak), özel dönüştürme operatörleri (dönüştürülecek sınıfta tanımlanan) veya daha karmaşık mekanizmalar ( TypeConverterlar veya sınıf yöntemleri, örneğin) kullanılarak yapılabilir. Bunun ne olacağının farkında değilsiniz, ancak başarısız olabileceğinin farkındasınız (bu nedenle, daha kontrollü bir dönüşüm mümkün olduğunda IMO kullanmalısınız). Sizin durumunuzda, dönüşüm basitçe ayrıştırarak stringa double:

double value = Double.Parse(aStringVariable);

Elbette bu başarısız olabilir, bu yüzden yaparsanız, her zaman atabileceği istisnayı yakalamalısınız ( FormatException). Burada konu dışıdır, ancak a TryParsemevcut olduğunda onu kullanmalısınız (çünkü anlamsal olarak bunun bir sayı olmayabileceğini ve daha da hızlı olduğunu söylüyorsunuz ... başarısız olur).

.NET'teki dönüşümler birçok yerden gelebilir, TypeConverterkullanıcı tanımlı dönüştürme operatörleri ile örtük / açık yayınlar, IConvertibleyöntemlerin uygulanması ve ayrıştırılması (bir şeyi unuttum mu?). Onlar hakkında daha fazla ayrıntı için MSDN'ye bir göz atın.

Bu uzun cevabı bitirmek için, kullanıcı tanımlı dönüştürme operatörleri hakkında sadece birkaç kelime. Programcının bir türü diğerine dönüştürmek için bir cast kullanmasına izin vermek sadece şekerdir . Bu, bir sınıf içinde (döküm yapılacak olan) bir yöntemdir ve "Hey, eğer bu türü o türe dönüştürmek istiyorsa, ben yapabilirim" diyor. Örneğin:

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

Bu durumda açıktır çünkü başarısız olabilir, ancak bu uygulamaya izin verilir (bununla ilgili yönergeler olsa bile). Bunun gibi özel bir dizgi sınıfı yazdığınızı hayal edin:

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

Uygulamanızda "programcının hayatını kolaylaştırmaya" ve bu dönüşümü bir oyuncu kadrosu aracılığıyla ifşa etmeye karar verebilirsiniz (bunun daha az yazmak için bir kısayol olduğunu unutmayın). Hatta bazı diller buna izin verebilir:

double value = "123";

Herhangi bir türe örtük dönüşüme izin verme (kontrol çalışma zamanında yapılacaktır). Uygun seçeneklerle bu, örneğin VB.NET'te yapılabilir. Bu sadece farklı bir felsefe.

Onlarla ne yapabilirim?

Yani son soru, birini veya diğerini ne zaman kullanmanız gerektiğidir. Bakalım ne zaman açık bir döküm kullanabileceğinizi görelim:

  • Temel türler arasındaki dönüşümler.
  • objectBaşka herhangi bir türe dönüşümler (buna kutudan çıkarma da dahil olabilir).
  • Türetilmiş bir sınıftan temel sınıfa (veya uygulanan bir arabirime) dönüşümler.
  • Özel dönüştürme operatörleri aracılığıyla bir türden diğerine dönüşümler.

Sadece ilk dönüştürme yapılabilir, Convertböylece diğerleri için başka seçeneğiniz yoktur ve açık bir döküm kullanmanız gerekir.

Şimdi ne zaman kullanabileceğinizi görelim Convert:

  • Herhangi bir temel türden başka bir temel türe dönüştürme (bazı sınırlamalarla, bkz. MSDN ).
  • IConvertibleDiğer (desteklenen) herhangi bir türe uygulanan herhangi bir türden dönüşümler .
  • Bir bytediziden / diziye / dizeden dönüşümler .

Sonuçlar

IMO Convert, bir dönüşümün başarısız olabileceğini bildiğiniz her seferde (format nedeniyle, aralık nedeniyle veya desteklenmeyebileceğinden), aynı dönüşüm bir dönüştürme ile yapılabilse bile (başka bir şey yoksa) kullanılmalıdır. Niyetinizin ne olduğunu ve başarısız olabileceğini (hata ayıklamayı basitleştirerek) kodunuzu kimin okuyacağını netleştirir .

Diğer her şey için bir alçı kullanmanız gerekir, seçim yok, ancak daha iyi bir yöntem varsa, o zaman kullanmanızı öneririm. Örneğinizde 'den' stringe dönüştürme, double(özellikle kullanıcıdan metin geliyorsa) çok sık başarısız olacak bir şeydir, bu nedenle bunu olabildiğince açık hale getirmelisiniz (dahası üzerinde daha fazla kontrol sahibi olursunuz), örneğin bir TryParseyöntem kullanarak .

Düzenleme: aralarındaki fark nedir?

Güncellenen soruya ve daha önce yazdıklarımı tutmaya göre ( ne zaman kullanabileceğiniz / kullanmanız gerektiğine kıyasla bir cast'ı ne zaman kullanabileceğiniz hakkında Convert), netleştirilmesi gereken son nokta, aralarında fark olup olmadığıdır (dahası Convert, işlemleri gerçekleştirebilmesi için kullanır IConvertibleve IFormattablearayüzler yayınlara izin verilmez).

Kısa cevap evet, farklı davranıyorlar . ConvertSınıfı yardımcı yöntemler sınıfı olarak görüyorum, bu yüzden çoğu zaman bazı yararlar veya biraz farklı davranışlar sağlıyor. Örneğin:

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

Oldukça farklı, değil mi? Atma kesilir (hepimizin beklediği şeydir) ancak Converten yakın tam sayıya yuvarlama yapar (ve bunun farkında değilseniz bu beklenmeyebilir). Her dönüştürme yöntemi farklılıklar getirir, bu nedenle genel bir kural uygulanamaz ve duruma göre görülmelidir ... Diğer türlere dönüştürmek için 19 temel tür ... liste oldukça uzun olabilir, durum!


Sormak için soruyu değiştirdim Difference between casting and using the Convert.To() method. Aksi takdirde çok kapsamlı cevap. (Umarım sorum yeniden

@ edmastermind29 Soruyu biraz düzenledim, konu uzun bir cevap için bile çok uzun (listelenecek 300'den fazla olası dönüşüm). Dönüştürme, yalnızca yayınlara karşı değil, aynı zamanda "düz" IConvertible ve IFormattable arabirimlerine kıyasla fayda (veya yalnızca beklenmedik davranışlar?) Ekler.
Adriano Repetti

C'den ödünç alınan, doubletam sayıları temsil etmeyen değerlerin "dönüştürülebilir" olması gerektiği fikrinden hoşlanmıyorum int. Bir döküm örneğin bir alınırken durumlarda uygun paradigmayı görünüyor Int32bir değerleri double[]gerçek sayılar ve bir karışımını tutan Int32dönüştürüldü değerlerle doubleTemsil olmayan bir değer dönüştürmek için [çabasıyla tam içinde int32beklenmedik bir durum olduğunu belirtmek istiyorum ve bir istisnayı tetiklemelidir], ancak kayıplı bir dönüşüm istediğinde kişinin istediği biçim konusunda spesifik olması gerektiğini düşünüyorum.
supercat

1
Diğer bir fark, nesneden ilkel tiplere. egobject o = 123; var l = Convert.ToInt64(o); var i = (long) (int) o; var f = (long) o // InvalidCastException
yue shi

1
@ rory.ap bu önemli bir nokta. Hayır, resmi olarak bu bir cast ( float-> int) değil, bir zorlamadır . Bir oyuncu kadrosu örneğin DerivedClass-> olabilir BaseClass. Kafa karıştırıcı çünkü C # 'da her ikisi için aynı kelimeyi (ve operatörü) kullanıyoruz ama aslında bunlar farklı şeyler. Aralarında ayrım yapmak için resmi bir tanım yazdığımdan biraz daha karmaşık.
Adriano Repetti

13

Döküm, derleyiciye şunu söylemenin bir yoludur: "Bu değişkenin bir Çubuk olduğunu düşündüğünü biliyorum, ama ben senden daha fazlasını biliyorum; nesne aslında bir Foo, bu yüzden ona bir Foo şu andan itibaren." Ardından, çalışma zamanında, gerçek nesnenin gerçekten bir Foo olduğu ortaya çıkarsa, kodunuz çalışır, nesnenin hiç Foo olmadığı ortaya çıkarsa, o zaman bir istisna alırsınız. (Özellikle bir System.InvalidCastException.)

Öte yandan dönüştürme, "Bana Bar türünde bir nesne verirseniz, o Bar nesnesinin içindekileri temsil eden yepyeni bir Foo nesnesi oluşturabilirim. Orijinal nesneyi değiştirmeyeceğim, kazandı" demenin bir yoludur. t o olacak, farklı orijinal nesneyi tedavi sadece bazı diğer değerine dayanan yeni bir şey yaratmak . o bunu nasıl yapacağınıza gelince, bir şey olabilir. hâlinde Convert.ToDoublebunun çağırarak sona erecekDouble.ParseHangi tür dizelerin hangi sayısal değerleri temsil ettiğini belirlemek için her türlü karmaşık mantığa sahip. Dizeleri farklı şekilde iki katına çıkaran kendi dönüştürme yönteminizi yazabilirsiniz (belki de roma rakamları veya her neyse, sayıları görüntülemek için tamamen farklı bazı kuralları desteklemek için). Bir dönüşüm her şeyi yapabilir, ancak fikir şu ki, derleyiciden sizin için hiçbir şey yapmasını istemiyorsunuz; Eğer derleyici, senin yardımın olmadan, bir (örnek olarak) eşleştirmek için nasıl bilmenin bir yolu vardır, çünkü yeni bir nesne oluşturmak için nasıl belirlemek için kod yazarken biridir stringa double.

Peki, ne zaman dönüşüyorsunuz ve ne zaman rol alıyorsunuz? Her iki durumda da bir tür değişkenimiz var, diyelim ki A ve B türünde bir değişkenimiz olsun istiyoruz. A nesnemiz gerçekten, aslında, kaputun altında bir B ise, o zaman çeviririz. Gerçekten bir B değilse, onu dönüştürmemiz ve programın bir A'dan nasıl B alacağını tanımlamamız gerekir.


Bir SO gönderisinde Eric Lippert, örtük döküm denen böyle bir şey olmadığından ve bunun örtük dönüştürme olduğundan bahsetti . Cast ve dönüşümleri birbirinin yerine kullanıyorum. "Örtük cast" demenin nesi yanlış? Dönüştürme, herhangi bir atama gerektirmeden örtükse, bunun bir "örtük döküm" olduğu söylenemez mi?
rahulaga_dev

1
@RahulAgarwal Atma nedir , belirli bir türün başka bir türün geçerli bir örneği olduğunu (veya yapılabileceğini) açıkça belirtmeniz gereken bir işlemdir . Örtük bir dönüştürme olduğunda, türü başka bir tür olarak ele almak için dönüştürme gerekmez . Yani "örtük döküm" demek pek bir anlam ifade etmiyor (Eric'in bahsettiği gibi geliştirici yazmadan bir döküm operatörünün eklendiği birkaç durum dışında, örneğin a kullanırken olduğu gibi foreach). Bu istisnaların dışında, yayınlar tanım gereği açıktır.
2018

6

Kimden MSDN:

Açık dönüşümler (yayınlar): Açık dönüşümler bir döküm operatörü gerektirir. Dönüştürme sırasında bilgi kaybolduğunda veya dönüştürme başka nedenlerden ötürü başarılı olamadığında çevrim gereklidir . Tipik örnekler, daha az hassasiyete veya daha küçük aralığa sahip bir türe sayısal dönüşüm ve bir temel sınıf örneğinin türetilmiş bir sınıfa dönüştürülmesini içerir.

Aşağıdaki örneği düşünün:

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

Ve ayrıca:

Bir dönüşüm, derleyiciye dönüştürmeyi planladığınız ve veri kaybının meydana gelebileceğinin farkında olduğunuzu açıkça bildirmenin bir yoludur.

Uyumlu olmayan türler System.Convertarasında dönüştürme yapmak istediğinizde sınıfı kullanabilirsiniz . Temel fark arasındaki döküm ve dönüştürmek olduğunu derleme ve çalışma zamanı . Tür dönüştürme istisnaları çalışma zamanında ortaya çıkar , yani çalışma zamanında başarısız olan bir tür ataması atılmasına neden olur . InvalidCastException


Sonuç: Yayınlama sırasında derleyiciye agerçekten tip olduğunu söylüyorsunuz bve eğer öyleyse proje bu örnekte olduğu gibi herhangi bir hata olmadan inşa edilir:

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

Ama dönüşüm sen yeni bir nesne oluşturmak için bir yol var derleyici söylüyorsun aÇeşidi b, bunu ve Proje herhangi hatasız yapıyor ancak dediğim gibi lütfen tip dökme çalışma anında başarısız olursa, bir neden olacaktır InvalidCastExceptioniçin fırlatılmak .

Örneğin, aşağıdaki kod asla derlenmez çünkü derleyici tür ifadesini türe DateTimedönüştüremediğini algılar int:

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

Ancak bu başarıyla derlendi:

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

Ancak çalışma zamanında şunu söyleyeceksiniz InvalidCastException:

"DateTime" dan "Int32" ye geçersiz atama.


4

Örneğinizde, bir dizeyi çift (integral olmayan tip) olarak çevirmeye çalışıyorsunuz.

Çalışması için açık bir dönüştürme gereklidir.

Bir int türüne dönüştürdüğünüzde çift değerin kesirli kısımlarını kaybedebileceğinizden Convert.ToDoubleyerine kullanmış olabileceğinizi belirtmeliyim Convert.ToInt64.

Değişkeniniz "5.25" değerine sahipse, varDouble 5,00 olurdu (Int64'e Dönüştürme nedeniyle 0,25 kayıp)

Yayınlama ve dönüştürme hakkındaki sorunuza cevap vermek için.

Oyuncunuz (açık bir kadro), açık bir kadro için gereksinimleri karşılamıyor. cast operatörü ile çevirmeye çalıştığınız değer geçersiz (yani integral değil).

Yayın / dönüştürme kuralları için bu MSDN Sayfasını ziyaret edin


@ edmastermind29 cevabımı güncelledim. umarım sorunuzu cevaplar.
2013

Sorumla ilgili olarak ... açık bir döküm için gereksinimler nelerdir? "Tam olmayan" değer açısından mı?

@ edmastermind29 Evet. sayısal bir türe çevirmeye çalıştığınız değer sayısal değilse, çevrim geçersizdir .. bir dönüştürme gereklidir.
scartag

4

Convert.DoubleYöntem aslında sadece dahili olarak çağırır Double.Parse(string)yöntemi.

Ne Stringtür ne de Doubletür, iki tür arasında açık / örtük bir dönüşümü tanımlamaz, bu nedenle çevrim her zaman başarısız olur.

Double.ParseYöntem her karakterin bakacağız stringve karakter değerlerine dayalı sayısal bir değer oluşturmak string. Karakterlerden herhangi biri geçersizse, Parseyöntem başarısız olur ( Convert.Doubleyöntemin de başarısız olmasına neden olur).


1
Ve bunun açık bir oyuncu kadrosundan farkı nedir?

3
Açık bir tür, veri türünün ne olduğuna bakmaz, yalnızca baytlara bakar. Bir örnek char x = '1'i bir tamsayıya çevirmek olabilir, tam sayı 49 olur çünkü ascii tablosundaki' 1 'karakteri # 49
user1751547

@ user1751547 Peki, kullanıcı Convert.ToDouble()baytların ötesine bakıp verileri dikkate alır mı?

@ user1751547 Bence bu soruyu doğru bir şekilde cevaplamak için gerekli olan sezginin bir türü. Basitçe "tanımlanmadı" demek biraz tartışmalı.
Ant P

@ edmastermind29 Evet, girdi türüne bakardı ve eğer bir dizge olsaydı, char'ın ascii değeri 49 ise, o zaman '1' karakteri olduğunu bilerek her karakterin üzerinden
geçerdi

3

Döküm herhangi bir dönüştürme içermez, yani bir değerin dahili temsili değişmez. Misal:

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.

Bir Sen dönüştürebilirsiniz doubleiçin stringböyle

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

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

Bir dönüştürebilir stringa double(bunlardan sadece iki burada) çeşitli şekillerde:

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

Veya güvenli yol

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

Convert.ToDouble()dahili aramalarDouble.Parse() . Convert.ToDouble()Üzerinde kullanmak Double.Parse()ya da kullanmamak benim yararıma mı ve neden?

Convert.ToDoublefarklı girdi türlerini kabul eden çok sayıda aşırı yüklemeye sahiptir. Aşırı yük kabul eden bir dizge geçilirse stringdöner . Bunun dışında kullanımda bir avantaj göremiyorum. 0.0null
Olivier Jacot-Descombes

Öyleyse, ya da ... ya da Double.Parse()düşünmem gereken bir teklif mi var?

Double.Parse()daha doğrudandır Convert.ToDouble(). Dizinizin geçerli bir numara içereceğinden eminseniz, güvenle kullanabilirsiniz, aksi takdirde kullanmanızı tavsiye ederim Double.TryParse.
Olivier Jacot-Descombes

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

Yukarıdaki dönüşüme dil tarafından izin verilmez. Sayısal türler için açık atamaların bir listesi: http://msdn.microsoft.com/en-us/library/yht2cx7b.aspx Gördüğünüz gibi, her sayısal tür bile başka bir sayısal türe dönüştürülemiyor

Burada yayınlama hakkında daha fazla bilgi

Bunun Convert.ToDouble () 'dan farkı nedir?

Bir tür çevirdiğinizde, veri yapısı değişmez. Sayısal değerlerin dönüşümü durumunda, birkaç bit kaybedebilir veya birkaç ek 0 bit elde edebilirsiniz. Ama hala bir numara ile çalışıyorsun. Sadece o sayı tarafından alınan bir bellek miktarını değiştiriyorsunuz. Bu, derleyicinin gereken her şeyi yapması için yeterince güvenlidir.

Ancak dizeyi bir sayıya çevirmeye çalıştığınızda, bunu yapamazsınız çünkü değişken tarafından alınan bellek miktarını değiştirmek yeterli değildir. Örneğin 5,00dize olarak "sayılar" dizisidir: 53 (5) 46 (.) 48 (0) 48 (0) - bu ASCII içindir, ancak dizi benzer bir şey içerecektir. Derleyici bir dizeden sadece ilk N (çift için 4? Emin değilim) bayt alacaksa - bu parça tamamen farklı bir çift sayı içerecektir. Aynı zamanda Convert.ToDouble (), bir dizenin her sembolünü alacak, temsil ettiği basamağı bulacak ve dize bir sayıyı temsil ediyorsa sizin için çift sayı yapacak özel bir algoritma çalıştırır. PHP gibi diller, kabaca, arka planda sizin için Convert.ToDouble'ı çağırır. Ancak C #, statik olarak yazılmış bir dil gibi, bunu sizin için yapmayacaktır. Bu, herhangi bir işlemin güvenli olduğundan emin olmanızı sağlar ve aşağıdakiler gibi beklenmedik bir şey yapmazsınız:

double d = (double)"zzzz"

@ edmastermind29 güncellenmiş cevabımı gör. Bunu açıklamaya çalıştım. Açıklama mükemmel olmaktan uzaktır, ancak farkı açıkladığını varsayalım.
Viktor S.

1

Bir dizeyi bir çifte benzer şekilde çevirmek C # 'a izin verilmez, bu nedenle bir İstisna elde edersiniz, dizeyi dönüştürmeniz gerekir ( kabul edilebilir dönüşüm yollarını gösteren MSDN belgesi ). Bunun nedeni, bir dizenin sayısal veri içermesi gerekmemesi, ancak çeşitli sayısal türlerin (boş değerler hariç) olmasıdır. A Convert, dizeyi sayısal bir değere dönüştürülüp dönüştürülemeyeceğini görmek için kontrol edecek bir yöntem çalıştıracaktır. Mümkünse, o değeri döndürür. Yapamazsa, bir istisna atar.

Dönüştürmek için birkaç seçeneğiniz var. Sorunuzda büyük ölçüde benzer olan Convertyöntemi kullandınız , ancak aşağıdakileri yapmanıza izin verecek olan TryParse'a da bakmalısınız :ParseConvert

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.
}

Bu, denemeniz durumunda olası istisnayı Convertveya Parsesayısal olmayan bir dizeyi önler .


Bir kullanmak benim için avantaj mı TryParseover Convertçünkü TryParsekontroller dönüşüm başarılı olursa?

@ edmastermind29 Ben öyle düşünüyorum. Dönüştürme işlemi başarısız olursa bir istisna atar. TryParse, dönüştürme başarılı olursa True ve başarısız olursa False bir boole döndürür.
Keen

1

double varDouble = (double)variablebunun variablezaten bir çift olduğunu varsayar . Eğer variablebir çift (bir dize var) değil o zaman bu başarısız olacaktır. double varDouble = Convert.ToDouble(variable)söylediği gibi - dönüştürür. Bir ikiliyi ayrıştırabilir veya başka bir şekilde çıkarabilirse, variableo zaman olacaktır.

Kullanıyorum Double.Parseya Double.TryParseda daha açık bir şekilde ne olması gerektiğini gösteriyor. Bir dizeyle başlıyorsunuz ve onun bir ikiye katlanmasını bekliyorsunuz. Herhangi bir şüpheniz varsa kullanın TryParse.

Eğer variablebir yöntem argümanı, ikiye katlama türünü değiştirmek. Doğru türü sağlamaktan arayanın sorumlu olmasını sağlayın. Bu şekilde derleyici işi sizin için yapar.


-1

En önemli fark, tür atama kullanılırsa ve dönüştürme başarısız olursa (diyelim ki çok büyük bir float değerini int'e dönüştürüyoruz) hiçbir istisna atılmayacak ve bir int'in tutabileceği minimum değer gösterilecektir. Ancak, Dönüştürme kullanılması durumunda, bu tür senaryolar için bir istisna atılacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.