Döküm ve zorlama arasındaki fark nedir?


86

Çeşitli çevrimiçi açıklamalarda her iki terimin de neredeyse birbirinin yerine kullanıldığını gördüm ve danıştığım ders kitaplarının çoğu da ayrım konusunda tam olarak net değil.

Bildiğiniz farkı açıklamanın belki de açık ve basit bir yolu var mı?

Tür dönüştürme (bazen tür atama olarak da bilinir )

Bir diğerini bekleyen bir bağlamda bir türün değerini kullanmak için.

Dönüştürmeyen tip atama (bazen tür kelime oyunu olarak bilinir )

Temeldeki bitleri değiştirmeyen bir değişiklik.

Zorlama

Bir derleyicinin, bir türdeki değeri, çevreleyen bağlam tarafından bu ikinci tür gerekli olduğunda otomatik olarak başka bir türden bir değere dönüştürdüğü işlem.


Yanıtlar:


115

Tür Dönüşümü :

Kelime dönüşümü , bir değerin bir veri türünden diğerine örtük olarak veya açıkça değiştirilmesini ifade eder, örneğin 16 bitlik bir tamsayı 32 bitlik tam sayıya.

Zorlama kelimesi örtük bir dönüşümü belirtmek için kullanılır.

Kelime dökümü, tipik olarak, bunun bir bit modelinin yeniden yorumlanması veya gerçek bir dönüşüm olup olmadığına bakılmaksızın, açık bir tür dönüşümüne (örtük bir dönüştürmenin aksine) karşılık gelir.

Öyleyse, zorlama örtüktür, biçimlendirme açıktır ve dönüştürme bunlardan herhangi biridir.


Birkaç örnek ( aynı kaynaktan ):

Zorlama (örtük):

double  d;
int     i;
if (d > i)      d = i;

Oyuncular (açık):

double da = 3.3;
double db = 3.3;
double dc = 3.4;
int result = (int)da + (int)db + (int)dc; //result == 9

bu "örtük zorlamayı" gereksiz kılar mı? notu burada hem "örtük zorlama" ve "açık zorlama" kullanır
Dave Cousineau

1
Örtük dönüştürme yalnızca hassasiyeti kaybetmediğinizde veya mantıklı olmadığında yapılabilir (Örn .: Int -> double). Çoğu modern dilde, double-> int yapamazsınız çünkü hassasiyeti kaybedersiniz. Tür zorlamasıyla bu bir "sorun" değildir.
Maxime Rouiller

1
Bu yanıt, CIL için ecma 335'te tanımlanan spesifikasyonlarla uyumlu değildir. Cevabımda örneklerle şartname tanımını belirledim.
P. Brian.Mackey

24

Sizin de belirttiğiniz gibi kullanımlar değişiklik gösterir.

Kişisel kullanımlarım:

  • Bir "döküm", bir döküm operatörünün kullanımıdır . Bir döküm operatörü, derleyiciye (1) bu ifadenin belirli bir türde olduğunun bilinmediğini, ancak size söz veriyorum, değerin çalışma zamanında bu türden olacağına dair talimat verir; derleyici, ifadeyi belirli bir türde olarak ele almaktır ve değilse çalışma zamanı bir hata üretecektir veya (2) ifade tamamen farklı bir türdeyse, ancak örnekleri ilişkilendirmenin iyi bilinen bir yolu vardır. dönüştürme türünün örnekleriyle ifade türünün. Derleyiciye, dönüşümü gerçekleştiren kod üretmesi talimatı verilir. Dikkatli okuyucu, bunların zıtlar olduğuna dikkat edecek ve bence bu güzel bir numara.

  • Bir "dönüştürme", bir türdeki bir değerin başka bir türün değeri olarak değerlendirildiği bir işlemdir - genellikle farklı bir tür, ancak teknik olarak "kimlik dönüştürme" yine de bir dönüşümdür. Dönüştürme, int'den double'a gibi "temsil değiştirme" olabilir veya dizeden nesneye gibi "gösterimi koruyan" olabilir. Dönüşümler, bir dönüştürme gerektirmeyen "örtük" veya bir dönüştürme gerektiren "açık" olabilir.

  • Bir "zorlama", temsili değiştiren örtük bir dönüştürmedir.


1
Sanırım bu cevabın ilk cümlesi en önemli şey. Farklı diller bu terimleri oldukça farklı şeyler ifade etmek için kullanır. Örneğin Haskell'de bir "zorlama" temsili asla değiştirmez; güvenli bir zorlama, Data.Coerce.coerce :: Coercible a b => a -> baynı temsile sahip olduğu kanıtlanmış tipler için çalışır; Unsafe.Coerce.unsafeCoerce :: a -> bherhangi iki tip için işe yarar (ve yanlış kullanırsanız iblislerin burnunuzdan çıkmasına neden olur).
dfeuer

@dfeuer ilginç veri noktası, teşekkürler! C # spesifikasyonunun "zorlama" yı tanımlamadığını not ediyorum; benim önerim kişisel olarak kastettiğim şey. Terimin kötü tanımlanmış göründüğü göz önüne alındığında, genellikle ondan kaçınırım.
Eric Lippert

9

Dönüşüm, bir nesne türünü başka bir tür olarak ele aldığınız işlemdir, Zorlama bir nesneyi diğerine dönüştürmektir.

Önceki süreçte herhangi bir dönüştürme söz konusu değildir, başka bir tür olarak ele almak istediğiniz bir türe sahip olduğunuzu, örneğin bir temel türden miras alan 3 farklı nesneniz olduğunu ve bunu alacak bir yönteminiz olduğunu unutmayın. temel tür, herhangi bir noktada, belirli alt türü biliyorsanız, onu olduğu gibi CAST yapabilir ve o nesnenin tüm belirli yöntemlerini ve özelliklerini kullanabilirsiniz ve bu, nesnenin yeni bir örneğini oluşturmaz.

Öte yandan, zorlama, yeni türün hafızasında yeni bir nesnenin yaratılması anlamına gelir ve ardından orijinal tür, her iki nesneyi de bellekte bırakarak (Çöp Toplayıcıları birini veya her ikisini de kaldırana kadar) yenisine kopyalanır. .

Örnek olarak aşağıdaki kodu göz önünde bulundurun:

class baseClass {}
class childClass : baseClass {}
class otherClass {}

public void doSomethingWithBase(baseClass item) {}

public void mainMethod()
{
    var obj1 = new baseClass();
    var obj2 = new childClass();
    var obj3 = new otherClass();

    doSomethingWithBase(obj1); //not a problem, obj1 is already of type baseClass
    doSomethingWithBase(obj2); //not a problem, obj2 is implicitly casted to baseClass
    doSomethingWithBase(obj3); //won't compile without additional code
}
  • obj1, zaten aynı türde olduğu için herhangi bir dönüştürme veya zorlama (dönüştürme) olmadan geçirilir baseClass
  • obj2 örtük olarak tabana dönüştürülür, yani yeni bir nesne oluşturulmaz, çünkü obj2 zaten olabilir baseClass
  • obj3'ün bir şekilde tabana dönüştürülmesi otherClassgerekiyor baseClass, ' den' e dönüştürmek için kendi yönteminizi sağlamanız gerekecek , bu yeni bir baseClass nesnesi oluşturmayı ve obj3'ten verileri kopyalayarak doldurmayı içerecektir.

İyi bir örnek, farklı türler arasında dönüştürmek için özel kod sağlayan Convert C # sınıfıdır .


4
Bir örnek, yapmaya çalıştığınız ayrımı netleştirmeye yardımcı olabilir.
Oliver Charlesworth

2

Döküm, nesnelerin türünü korur. Baskı yapmaz.

Zorlama , atamayla uyumlu OLMAYAN bir türün değerini almak ve atamayla uyumlu bir türe dönüştürmektir. Burada bir zorlama yapıyorum çünkü Int32miras ALMAZ Int64... yani atama uyumlu DEĞİLDİR. Bu genişleyen bir zorlamadır (veri kaybı yok). Genişleyen bir baskı, örtük bir dönüşümdür . Bir Zorlama bir dönüşüm gerçekleştirir.

void Main()
{
    System.Int32 a = 100;
    System.Int64 b = a;
    b.GetType();//The type is System.Int64.  
}

Döküm ayrıca ederken farklı bir tipte sanki bir tür tedavi etmek için izin verir türünü koruyarak .

    void Main()
    {
        Derived d = new Derived();
        Base bb = d;
        //b.N();//INVALID.  Calls to the type Derived are not possible because bb is of type Base
        bb.GetType();//The type is Derived.  bb is still of type Derived despite not being able to call members of Test
    }

    class Base 
    {
        public void M() {}
    }

    class Derived: Base
    {
        public void N() {}
    }

Kaynak: James S. Miller tarafından Açıklamalı Ortak Dil Altyapısı Standardı

Şimdi tuhaf olan, Microsoft'un Casting hakkındaki belgelerinin, Casting'in ecma-335 spesifikasyon tanımıyla uyumlu olmamasıdır.

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

... Bu, Zorlamalar Kullanmıyor gibi geliyor .

Örneğin,

  object o = 1;
  int i = (int)o;//Explicit conversions require a cast operator
  i.GetType();//The type has been explicitly converted to System.Int32.  Object type is not preserved.  This meets the definition of Coercion not casting.

Kim bilir? Belki Microsoft bu tür şeyleri okuyup okuyamadığını kontrol ediyordur.


1

Aşağıda aşağıdaki makaleden bir gönderi var :

Zorlama ve oyuncu seçimi arasındaki fark genellikle ihmal edilir. Nedenini anlayabiliyorum; birçok dil her iki işlem için de aynı (veya benzer) sözdizimine ve terminolojiye sahiptir. Hatta bazı diller herhangi bir dönüşüme "döküm" olarak atıfta bulunabilir, ancak aşağıdaki açıklama CTS'deki kavramlara atıfta bulunmaktadır.

Farklı türde bir konuma bir türden bir değer atamaya çalışıyorsanız, yeni türün orijinaline benzer anlamı olan bir değer üretebilirsiniz. Bu zorlamadır. Zorlama, bir şekilde orijinaline benzeyen yeni bir değer oluşturarak yeni türü kullanmanıza izin verir. Bazı zorlamalar verileri atabilir (örneğin, int 0x12345678'i kısa 0x5678'e dönüştürme), bazıları ise vermeyebilir (örneğin int 0x00000008'i kısa 0x0008'e veya uzun 0x0000000000000008'e dönüştürme).

Değerlerin birden çok türe sahip olabileceğini hatırlayın. Durumunuz biraz farklıysa ve değer türlerinden yalnızca farklı birini seçmek istiyorsanız, döküm işin aracıdır. Çevrim, bir değerin içerdiği belirli bir tür üzerinde işlem yapmak istediğinizi belirtir.

Kod seviyesindeki fark C # ile IL arasında değişir. C #'da hem döküm hem de zorlama oldukça benzer görünür:

static void ChangeTypes(int number, System.IO.Stream stream)
{
    long longNumber = number;
    short shortNumber = (short)number;

    IDisposable disposableStream = stream;
    System.IO.FileStream fileStream = (System.IO.FileStream)stream;
}

IL düzeyinde oldukça farklıdırlar:

ldarg.0
 conv.i8
 stloc.0

ldarg.0
 conv.i2
 stloc.1


ldarg.1
 stloc.2

ldarg.1
 castclass [mscorlib]System.IO.FileStream
 stloc.3

Mantıksal seviyeye gelince, bazı önemli farklılıklar vardır. Hatırlanması gereken en önemli şey, zorlamanın yeni bir değer yaratmasıdır, ancak döküm yapmaz. Orijinal değerin kimliği ve dökümden sonraki değer aynı iken, zorlanmış bir değerin kimliği orijinal değerden farklıdır; dönüştürme yeni, farklı bir örnek oluşturur, ancak döküm yapmaz. Bunun bir doğal sonucu, dökümün sonucunun ve orijinalin her zaman eşdeğer olacağı (hem özdeşlik hem de eşitlik açısından), ancak zorunlu bir değer orijinaline eşit olabilir veya olmayabilir ve asla orijinal kimliği paylaşmaz.

Sayısal türler her zaman değere göre kopyalandığından, yukarıdaki örneklerde zorlamanın sonuçlarını görmek kolaydır. Referans türleriyle çalışırken işler biraz daha karmaşık hale gelir.

class Name : Tuple<string, string>
{
    public Name(string first, string last)
        : base(first, last)
    {
    }

    public static implicit operator string[](Name name)
    {
        return new string[] { name.Item1, name.Item2 };
    }
}

Aşağıdaki örnekte, bir dönüştürme, diğeri bir zorlamadır.

Tuple<string, string> tuple = name;
string[] strings = name;

Bu dönüşümlerden sonra tuple ve name eşittir, ancak dizeler ikisine de eşit değildir. Bir Name ile bir dizeyi [] karşılaştırmak için Name sınıfına Equals () ve operator == () uygulayarak durumu biraz daha iyi (veya biraz daha kafa karıştırıcı) yapabilirsiniz. Bu operatörler karşılaştırma sorununu "düzeltir", ancak yine de iki ayrı örneğiniz olur; Dizelerde yapılan herhangi bir değişiklik ad veya dizide yansıtılmazken, ad veya demetten birinde yapılan değişiklikler ad ve tuple'a yansıtılır, ancak dizelerde yansıtılmaz.

Yukarıdaki örnek, döküm ve zorlama arasındaki bazı farklılıkları göstermeyi amaçlasa da, C # 'da referans türleriyle dönüştürme operatörlerini kullanma konusunda neden son derece dikkatli olmanız gerektiğine dair harika bir örnek teşkil eder.


1

Gönderen CLI standardı :

I.8.3.2 Zorlama

Bazen, bir konuma atanamayan bir türden bir değer almak ve değeri konumun türüne atanabilir bir türe dönüştürmek istenebilir. Bu, değerin zorlanmasıyla başarılır . Zorlama, belirli bir türden ve istenen türde bir değer alır ve orijinal değerle eşdeğer anlama sahip olan istenen türde bir değer yaratmaya çalışır. Zorlama, tür değişikliğinin yanı sıra temsil değişikliğine neden olabilir; bu nedenle baskı, nesne kimliğini zorunlu olarak korumaz.

İki tür zorlama vardır: bilgiyi asla kaybetmeyen genişletme ve bilginin kaybolabileceği daraltma . Genişletme zorlamasına bir örnek, 32 bitlik işaretli tam sayı olan bir değeri 64 bitlik işaretli tam sayı olan bir değere zorlamak olabilir. Daraltma zorlamasının bir örneği, bunun tersidir: 64 bitlik işaretli bir tamsayının 32 bitlik işaretli bir tam sayıya zorlanması. Programlama dilleri genellikle genişleme zorlamalarını örtük dönüştürmeler olarak uygularken , daraltıcı baskılar genellikle açık bir dönüştürme gerektirir .

Bazı zorlamalar, yerleşik tiplerde doğrudan VES işlemlerine dahil edilmiştir (bkz. §I.12.1). Diğer tüm baskılar açıkça talep edilecektir. Yerleşik türler için CTS, işlem anlamlarına göre çalışma zamanı denetimleri olmadan genişletme zorlamaları ve çalışma zamanı denetimleri veya kesme ile daraltma zorlamaları gerçekleştirmek için işlemler sağlar.

I.8.3.3 Döküm

Bir değer birden fazla türde olabileceğinden, değerin kullanımının hangi türlerinin kullanıldığını açıkça belirlemesi gerekir. Değerler, yazılan konumlardan okunduğu için, kullanılan değerin türü, değerin okunduğu konumun türüdür. Farklı tür kullanılacak ise, değer döküm diğer türlerinden biri olabilir. Çevrim genellikle bir derleme zamanı işlemidir, ancak derleyici değerin hedef tipte olduğunu statik olarak bilemezse, bir çalışma zamanı çevrim denetimi yapılır. Zorlamadan farklı olarak, bir döküm asla bir nesnenin gerçek türünü değiştirmez veya temsilini değiştirmez. Döküm, nesnelerin kimliğini korur.

Örneğin, belirli bir arayüzün değerini tutacak şekilde yazılan bir konumdan okunan bir değeri yayınlarken bir çalışma zamanı kontrolü gerekli olabilir. Bir arabirim, değerin eksik bir açıklaması olduğundan, bu değerin farklı bir arabirim türünde olması genellikle bir çalışma zamanı dönüştürme denetimiyle sonuçlanır.


1

Wikipedia'ya göre,

Bilgisayar biliminde, tür dönüştürme, tür atama, tür zorlama ve tür hokkabazlığı, bir ifadeyi bir veri türünden diğerine değiştirmenin farklı yollarıdır.

Tip döküm ve tip zorlama arasındaki fark aşağıdaki gibidir:

           TYPE CASTING           |                   TYPE COERCION
                                  |
1. Explicit i.e., done by user    | 1. Implicit i.e., done by the compiler
                                  |
2. Types:                         | 2. Type:
    Static (done at compile time) |     Widening (conversion to higher data 
                                  |     type)
    Dynamic (done at run time)    |     Narrowing (conversion to lower data 
                                  |     type)
                                  |
3. Casting never changes the      | 3. Coercion can result in representation 
   the actual type of object      |    as well as type change.
   nor representation.            |

Not : Döküm, dönüştürme değildir. Bu sadece bir nesne türünü başka bir tür olarak ele aldığımız süreçtir. Bu nedenle, gerçek nesne türü ve temsili, döküm sırasında değişmez.

@ PedroC88'in sözlerine katılıyorum:

Öte yandan, zorlama, yeni türün hafızasında yeni bir nesnenin yaratılması anlamına gelir ve ardından orijinal tür, her iki nesneyi de bellekte bırakarak (Çöp Toplayıcıları birini veya her ikisini de kaldırana kadar) yenisine kopyalanı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.