SORU
30 Ocak 2009, Cuma


Döküm vs CLR 'kelime olarak' kullanarak

Programlama arabirimleri, döküm veya nesne türü dönüştürme bir çok şey yapıyorum buldum.

Dönüşüm bu iki yöntem arasında bir fark var mı? Eğer öyleyse, maliyet farkı var ya da nasıl bu programı etkiler mi?

public interface IMyInterface
{
    void AMethod();
}

public class MyClass : IMyInterface
{
    public void AMethod()
    {
       //Do work
    }

    // Other helper methods....
}

public class Implementation
{
    IMyInterface _MyObj;
    MyClass _myCls1;
    MyClass _myCls2;

    public Implementation()
    {
        _MyObj = new MyClass();

        // What is the difference here:
        _myCls1 = (MyClass)_MyObj;
        _myCls2 = (_MyObj as MyClass);
    }
}

Ayrıca, "genel" tercih edilen yöntem içinde ne var?

CEVAP
30 Ocak 2009, Cuma


Cevapları şu ana kadar herhangi bir cevap başlatmak anda!) sanmıyorum hangi kullanarak değer gerçekten açıkladı.

  • Bunu yapma:

    // Bad code - checks type twice for no reason
    if (randomObject is TargetType)
    {
        TargetType foo = (TargetType) randomObject;
        // Do something with foo
    }
    

    Sadece bu kontrol iki kez, ama eğer randomObject yerel değişken yerine bir alan ise farklı şeyler kontrol edilebilir. "Eğer başka bir iş parçacığı bu ikisi arasındaki randomObject değeri değişirse" pas ama başarısız dökme sonra. eğer bu mümkün değil

  • randomObject gerçektengerekireğer değilse, bir hata var demektir TargetType, yani örnek olmak, sonra döküm doğru çözümdür. Bu iş yanlış varsayımlar altında yapılan anlamına gelir, derhal bir özel durum atar ve durumu doğru hata türünü gösterir.

    // This will throw an exception if randomObject is non-null and
    // refers to an object of an incompatible type. The cast is
    // the best code if that's the behaviour you want.
    TargetType convertedRandomObject = (TargetType) randomObject;
    
  • randomObjectolabilirTargetType TargetType bir örnek olacak bir başvuru türü, o zaman bu gibi bir kod kullanın:

    TargetType convertedRandomObject = randomObject as TargetType;
    if (convertedRandomObject != null)
    {
        // Do stuff with convertedRandomObject
    }
    
  • *18.* ^em>olabilirTargetType TargetType bir örnek olacak bir değer girin, ardından TargetType kendini as kullanamayız, ama null olabilecek bir tür kullanabilirsiniz:

    TargetType? convertedRandomObject = randomObject as TargetType?;
    if (convertedRandomObject != null)
    {
        // Do stuff with convertedRandomObject.Value
    }
    

    (Not: şu anda bu actually slower than is cast. Daha şık ve tutarlı olduğunu düşünüyorum, ama oraya gittik.)

  • Gerçekten dönüştürülen değer gerekmez, ama sadece olup olmadığını bilmek gerekirTargetType, sonra is operatörü bir örnek, senin arkadaşın. Bu durumda TargetType bir başvuru türü veya bir değer türü farketmez.

  • Olabilir diğer durumlarda ilgili jenerik nerede is yararlı (çünkü olmayabilir ya T bir başvuru türü veya değil, bu yüzden sen insan değilsin gibi) ama onlar daha az belirgin.

  • Neredeyse kesinlikle daha önce değer türü durum is null bir türünü kullanarak ve 27 ** hep beraber:) düşünce olmaması kullandım


EDİT: yukarıdakilerin hiçbiri performans hakkında, NULL değer türü kutulama aslında yavaş ama istikrarlı olduğunu kaydetti ettiğim değer türü durum, daha başka görüşmeler Unutmayın.

Başına naasking cevabı,-ve-cast veya-olarak hem de olabildiğince hızlı olarak ve boş çek ile modern JİTs de görüldüğü gibi kod aşağıda:

using System;
using System.Diagnostics;
using System.Linq;

class Test
{
    const int Size = 30000000;

    static void Main()
    {
        object[] values = new object[Size];
        for (int i = 0; i < Size - 2; i  = 3)
        {
            values[i] = null;
            values[i   1] = "x";
            values[i   2] = new object();
        }
        FindLengthWithIsAndCast(values);
        FindLengthWithIsAndAs(values);
        FindLengthWithAsAndNullCheck(values);
    }

    static void FindLengthWithIsAndCast(object[] values)        
    {
        Stopwatch sw = Stopwatch.StartNew();
        int len = 0;
        foreach (object o in values)
        {
            if (o is string)
            {
                string a = (string) o;
                len  = a.Length;
            }
        }
        sw.Stop();
        Console.WriteLine("Is and Cast: {0} : {1}", len,
                          (long)sw.ElapsedMilliseconds);
    }

    static void FindLengthWithIsAndAs(object[] values)        
    {
        Stopwatch sw = Stopwatch.StartNew();
        int len = 0;
        foreach (object o in values)
        {
            if (o is string)
            {
                string a = o as string;
                len  = a.Length;
            }
        }
        sw.Stop();
        Console.WriteLine("Is and As: {0} : {1}", len,
                          (long)sw.ElapsedMilliseconds);
    }

    static void FindLengthWithAsAndNullCheck(object[] values)        
    {
        Stopwatch sw = Stopwatch.StartNew();
        int len = 0;
        foreach (object o in values)
        {
            string a = o as string;
            if (a != null)
            {
                len  = a.Length;
            }
        }
        sw.Stop();
        Console.WriteLine("As and null check: {0} : {1}", len,
                          (long)sw.ElapsedMilliseconds);
    }
}

Dizüstü bilgisayarımda, bu tüm 60ms hakkında yürütülecek. İki şeye dikkat edin:

  • Aralarında önemli bir fark yok. (Aslında, artı-boş Çek olarak kesinlikle durum vardıryavaş. Yukarıdaki kod aslında yapar türünü kontrol etmek çok kolay, çünkü bir mühürlenmiş sınıf; eğer kontrol için bir arayüz, dengesi biraz lehine olarak-artı-boş kontrol edin.)
  • Tüm bunlardelicesinehızlı. Basitçe buolmazgerçekten yapmayacak sürece kodunuzda darboğaz olabilirhiçbir şeydeğerleri daha sonra.

Bakalım performansı hakkında endişe değil. Hadi doğruluğu ve tutarlılığı hakkında endişe.

Ben korumak ve dökme (veya-olarak) hem de güvenli olmayan zaman ile ilgili değişkenler olarak yazın değerini ifade eder Mayıs değişikliği nedeniyle başka bir iş parçacığı arasındaki test ve döküm. Bu oldukça nadir bir durum olurdu - ama bunun yerine sürekli kullanabileceğim bir sözleşme yapardım.

Ben de, "sonra da" boş Çek olarak kaygıları daha iyi ayrılmasını sağlar koruyun. Bir dönüşüm ve sonucu kullandığı bir deyim o zaman çalışır ve bir ifade var. -Ve-cast veya-olarak bir test gerçekleştirirsonrabir değeri dönüştürmek için çalışır.

Bir başka deyişle, ister herkeshiçyazma:

int value;
if (int.TryParse(text, out value))
{
    value = int.Parse(text);
    // Use value
}

-Ve döküm yerine daha ucuz bir şekilde belli olsa da ne yaptığını.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • BrandonHarrisWalker

    BrandonHarri

    27 Kasım 2006
  • chrmoe

    chrmoe

    7 Kasım 2006
  • Gigawipf

    Gigawipf

    18 ŞUBAT 2010