Downcasting'in doğru kullanımı nedir?


67

Alt yayın, bir temel sınıftan (veya arayüzden) bir alt sınıfa veya yaprak sınıfına döküm yapmak anlamına gelir.

Bir System.Objectbaşka yayın türünden başka bir gruba yayın yaparsanız aşağı akış örneği olabilir .

Downcasting popüler değil, belki de bir kod kokusu: Nesne Yönelimli doktrin, örneğin downcasting yerine sanal veya soyut yöntemleri tanımlama ve çağırmayı tercih etmektir.

  • Varsa, downcasting için iyi ve uygun kullanım durumları nelerdir? Diğer bir deyişle, hangi durumlarda, aşağıya yüklenen kod yazmak uygun olur?
  • Cevabınız "yok" ise, neden dil üstü yayıncılık neden destekleniyor?

5
Tanımladığınız şeye genellikle "downcasting" denir. Bu bilgiyle donanmışken, önce kendi araştırmalarınızı biraz daha yapabilir ve bulduğunuz nedenlerin yetersiz olduğunu açıklayabilir misiniz? TL; DR: downcasting statik yazmayı bozuyor, ancak bazen bir tür sistemi çok kısıtlayıcı. Bu nedenle, bir dilin güvenli bir downcasting sunması mantıklıdır.
amon

Aşağı yayın mı demek istiyorsun? Upcasting sınıf hiyerarşisinde, yani alt sınıftan üst sınıfa, alt sınıfın tersine, üst sınıftan alt sınıfa kadar olacaktır ...
Andrei Socaciu

Özür dilerim: haklısın. "Upcast" olarak değiştirilen soruyu "downcast" olarak değiştirdim.
ChrisW

@ amon en.wikipedia.org/wiki/Downcasting , örnek olarak "dizeye dönüştür" ifadesini verir (.Net bir sanal uygulamayı destekler ToString); diğer örneği "Java kapları" dır, çünkü Java, jenerik ilaçları desteklemez (C # yapar). stackoverflow.com/questions/1524197/downcast-and-upcast downcasting neyi diyor olduğunu , ancak ne zaman örnekleri olmadan uygun .
ChrisW

4
@ChrisW Bu before Java had support for generics, değil because Java doesn't support generics. Amon hemen hemen size cevap verdi - birlikte çalıştığınız tip sistemi çok kısıtlayıcı olduğunda ve değiştirecek konumda olmadığınız zaman.
Ordous

Yanıtlar:


12

İşte sağanaklığın bazı doğru kullanımları.

Ve ben burada saygısız bir şekilde, aşağıya doğru kullanımın kesinlikle bir kod kokusu olduğunu söyleyen diğerlerine şiddetle karşı çıkıyorum çünkü ilgili sorunları çözmenin başka makul bir yolu olmadığına inanıyorum.

Equals:

class A
{
    // Nothing here, but if you're a C++ programmer who dislikes object.Equals(object),
    // pretend it's not there and we have abstract bool A.Equals(A) instead.
}
class B : A
{
    private int x;
    public override bool Equals(object other)
    {
        var casted = other as B;  // cautious downcast (dynamic_cast in C++)
        return casted != null && this.x == casted.x;
    }
}

Clone:

class A : ICloneable
{
    // Again, if you dislike ICloneable, that's not the point.
    // Just ignore that and pretend this method returns type A instead of object.
    public virtual object Clone()
    {
        return this.MemberwiseClone();  // some sane default behavior, whatever
    }
}
class B : A
{
    private int[] x;
    public override object Clone()
    {
        var copy = (B)base.Clone();  // known downcast (static_cast in C++)
        copy.x = (int[])this.x.Clone();  // oh hey, another downcast!!
        return copy;
    }
}

Stream.EndRead/Write:

class MyStream : Stream
{
    private class AsyncResult : IAsyncResult
    {
        // ...
    }
    public override int EndRead(IAsyncResult other)
    {
        return Blah((AsyncResult)other);  // another downcast (likely ~static_cast)
    }
}

Bunların kod kokuları olduğunu söyleyecekseniz, onlar için daha iyi çözümler sunmanız gerekir (rahatsızlıktan kaçınılsalar bile). Daha iyi çözümlerin var olduğuna inanmıyorum.


9
"Kod kokusu", "bu tasarım kesinlikle kötü " anlamına gelmez, "bu tasarım şüpheli " anlamına gelir .
Doğası

5
@Caleth: Ve benim açımdan bu tasarımların her zaman ortaya çıktığı ve gösterdiğim tasarımlar hakkında kesinlikle şüpheli bir şey olmadığı ve dolayısıyla dökümün bir kod kokusu olmadığı.
Mehrdad

4
@Caleth Ben katılmıyorum. Bana göre kod kokusu, kodun kötü olduğu veya en azından geliştirilebileceği anlamına gelir.
Konrad Rudolph

6
@Mehrdad Sizce kod kokuları uygulama programcılarının hatası olmalı. Neden? Her kod kokusunun gerçek bir sorun olması veya bir çözümü olması gerekmez. Martin Fowler’a göre bir kod kokusu, basitçe “sistemdeki daha derin bir soruna karşılık gelen bir yüzey göstergesidir”, object.Equalsbu açıklamaya oldukça uyuyor (alt sınıfların doğru şekilde uygulanmasına izin veren bir üst sınıfta eşit bir sözleşme sağlamaya çalışın - kesinlikle ) önemsiz olmayan. Uygulama programcıları olarak çözemediğimiz (bazı durumlarda önleyebileceğimiz) farklı bir konudur.
Voo

5
@Mehrdad Pekala, orijinal dil tasarımcılarından birinin Eşittir hakkında söylediklerini görelim .. Object.Equals is horrid. Equality computation in C# is completely messed up(Eric'in cevabı üzerine yaptığı yorum). Dilin önde gelen tasarımcılarından birinin yanlış olduğunu söylediğinde bile fikrini tekrar gözden geçirmek istemediğin komik.
Voo

135

Downcasting popüler değil, belki bir kod kokusu

Katılmıyorum. Downcasting son derece popüler ; Çok sayıda gerçek dünya programı, bir veya daha fazla downcast içerir. Ve belki de bir kod kokusu değil. Öyle kesinlikle bir kod koku. Bu nedenle, indirme işleminin programın metninde tezahür etmesi zorunludur . Kokuyu daha kolay fark edebilmeniz ve kod incelemesine dikkat etmek için harcayacağınız şekilde.

Hangi durumda [ları] hangi indirmeleri kod yazmak uygun olur?

Herhangi bir durumda:

  • ifadenin derleme zamanı türünden daha belirgin olan bir ifadenin çalışma zamanı türü ile ilgili bir gerçek hakkında % 100 doğru bilgiye sahipseniz ve
  • Derleme zamanı türünde bulunmayan nesnenin yeteneğini kullanmak için bu gerçeğin avantajlarından yararlanmanız gerekir.
  • Oyuncu kadrosunu yazmak için zaman ve çabanın kullanılması, ilk iki noktanın herhangi birini ortadan kaldırmak için programı yeniden düzenlemekten daha iyidir.

Bir programı ucuza yeniden düzenleyebilir, böylece çalışma zamanı türü derleyici tarafından çıkarılabilir ya da daha fazla türetilmiş türün kapasitesine gerek duymamanız için programı yeniden düzenleyebilirseniz, bunu yapın. Programı yeniden düzenlemenin zor ve pahalı olduğu durumlar için dile aşağıya doğru yayınlar eklendi .

Neden downcasting dili tarafından destekleniyor?

C #, yapılacak işleri var pragmatik programcılar tarafından icat edilmiştir için yapılacak işler var pragmatik programcılar. C # tasarımcıları OO purists değildir. Ve C # tipi sistem mükemmel değildir; tasarım gereği, bir değişkenin çalışma zamanına yerleştirilebilecek kısıtlamaları hafife alır.

Ayrıca, downcasting C # ile çok güvenlidir. Downcast'in çalışma zamanında doğrulanacağına dair kesin bir garantimiz var ve eğer doğrulanamazsa program doğru olanı yapıyor ve çöküyor. Bu harika; % 100 doğru anlam anlayışı türünün% 99,99 doğru olduğu ortaya çıkarsa, programınız zamanın% 99,99'unu çalıştırır ve zamanın% 99,99'unu tahmin edilemez davranmak ve kullanıcı verilerini% 0,01 oranında bozmak yerine çöker. .


EGZERSİZ: Açık bir döküm operatörü kullanmadan C # ' da bir downcast üretmenin en az bir yolu vardır . Böyle bir senaryo düşünebiliyor musunuz? Bunlar aynı zamanda potansiyel kod kokuları olduğu için, kodda açık bir döküm yapmadan bir downcast çökmesine neden olabilecek bir özelliğin tasarımında hangi tasarım faktörlerinin kullanıldığını düşünüyorsunuz?


101
Duvardaki lisede bulunan posterleri hatırlayın "Popüler olan her zaman doğru değildir, doğru olan her zaman popüler değildir?" Seni lisede uyuşturucu kullanmaya ya da hamile kalmaya zorlamaya çalıştıklarını sanıyordun ama aslında teknik borcun tehlikeleri hakkında uyarıyorlardı.
corsiKa

14
Elbette @EricLippert, foreach bildirimi. Bu IEnumerable'ın jenerik olması için yapıldı, değil mi?
Arturo Torres Sánchez,

18
Bu açıklama günümü gün etti. Bir öğretmen olarak, sık sık C # 'nın neden bu şekilde veya bu şekilde tasarlandığını sorduğumda, cevaplarım genellikle sizin ve meslektaşlarınızın burada ve bloglarınızda paylaştığınız motivasyonlara dayanıyor. “Ama nedenyyyy?! ” Takip sorusuna cevap vermek genellikle biraz zor . Ve burada mükemmel takip cevabını buldum: "C # yapacak işleri olan pragmatik programcılar tarafından, işi yapacak pragmatik programcılar için icat edildi.". :-) @EricLippert!
Zano

12
Bir yana: Açıkçası yukarıdaki yorumumda , A'dan B'ye aşağıya doğru bir düşüşümüz olduğunu söylemek istedim. Sınıf hiyerarşisinde dolaşırken "yukarı" ve "aşağı" ve "ebeveyn" ve "çocuk" kullanımlarını gerçekten beğenmedim ve onları alıyorum Yazımda her zaman yanlış. Türler arasındaki ilişki bir üst / alt küme ilişkisidir, öyleyse neden bununla ilişkili bir yukarı veya aşağı yönü olması gerektiğini bilmiyorum. Beni bile "ebeveyn" olarak çalıştırma. Zürafanın ebeveyni, Memeli değil, Zürafanın ebeveyni, Bay ve Bayan Zürafa'dır.
Eric Lippert,

9
Object.Equalsolduğu korkunç . C # 'daki eşitlik hesaplaması tamamen karışık , bir yorumda açıklamak için fazla karışık. Eşitliği temsil etmenin birçok yolu var; onları tutarsız hale getirmek çok kolaydır; aslında çok kolaydır gerekli bir eşitlik operatörü (simetri, refleksivite ve geçişlilik) gerekli özelliklerini ihlal etmek. Bugün sıfırdan bir tip sistem tasarlıyor muydum, hiçbiri Equals(ya GetHashcodeda ya da ToString) olmazdı Object.
Eric Lippert

33

Olay işleyicileri genellikle imzaya sahiptir MethodName(object sender, EventArgs e). Bazı durumlarda olayı ne tür senderolduğuna bakılmaksızın veya hatta hiç kullanmadan kullanmak mümkündür sender, ancak bazılarında senderolayı işlemek için daha spesifik bir türe atılmalıdır.

Örneğin, iki TextBoxkişiniz olabilir ve her birinden bir etkinliği işlemek için tek bir temsilci kullanmak isteyebilirsiniz. Sonra olayı işlemek için gerekli özelliklere erişebilmeniz senderiçin bir döküm yapmanız gerekir TextBox:

private void TextBox_TextChanged(object sender, EventArgs e)
{
   TextBox box = (TextBox)sender;
   box.BackColor = string.IsNullOrEmpty(box.Text) ? Color.Red : Color.White;
}

Evet, bu örnekte, bunu TextBoxdahili olarak yapan kendi alt sınıfınızı oluşturabilirsiniz . Her zaman pratik ya da mümkün olmasa da.


2
Teşekkürler, bu iyi bir örnek. TextChangedOlay üyesidir Controlacaba neden - senderait tip değildir ControlYazmak yerine object? Ayrıca (teorik olarak) çerçevenin her alt sınıf için olayı yeniden tanımlayıp tanımlayamayacağını merak ettim (böylece, örneğin gönderenin türü olarak TextBoxkullanarak etkinliğin yeni bir sürümüne TextBoxsahip olabilir) ... için TextBox) TextBoxuygulama içinde (yeni olay türünü uygulamak için), ancak uygulama kodunun olay işleyicisinde bir downcast istemekten kaçının.
ChrisW

3
Bu kabul edilebilir olarak kabul edilir, çünkü her olayın kendi yöntem imzası varsa, olay işleme genelleştirmek zordur. Her ne kadar en iyi uygulama olarak kabul edilen bir şey yerine kabul edilebilir bir sınırlama olduğunu varsayalım, çünkü alternatif aslında daha zahmetli. Bir ile başlamak mümkün olsaydı TextBox senderziyade bir daha object senderaşırı kod sorunlara neden olmadan, ben bu yapılabilir eminim.
Neil

6
@Neil Olay sistemleri, rastgele veri parçalarının keyfi nesnelere iletilmesine izin vermek için özel olarak yapılmıştır. Bu tür doğruluk için çalışma zamanı kontrolleri olmadan yapmak mümkün değildir.
Joker_vD

@Joker_vD İdeal olarak API elbette genel kontravaryansı kullanarak güçlü bir şekilde yazılmış geri arama imzalarını destekleyecektir. .NET'in (ezici bir şekilde) bunu yapmaması, yalnızca jenerik ve kovaryansın daha sonra tanıtılmasından kaynaklanmaktadır. - Başka bir deyişle, temelde iyi bir fikir olduğu için, dilde / API'deki yetersizlikler nedeniyle burada (ve genel olarak başka bir yerde) aşağıya indirme gereklidir.
Konrad Rudolph

@KonradRudolph Tabii, ancak olay sıralamasında rastgele tür olaylarını nasıl saklarsınız? Sadece sıradan kurtulmaktan mı, doğrudan gönderimden mi geçiyorsun?
Joker_vD

17

Bir şey size bir süper tip verdiğinde ve çok alt tipe bağlı olarak farklı şekilde ele almanız gerektiğinde downcasting gerekir.

decimal value;
Donation d = user.getDonation();
if (d is CashDonation) {
     value = ((CashDonation)d).getValue();
}
if (d is ItemDonation) {
     value = itemValueEstimator.estimateValueOf(((ItemDonation)d).getItem());
}
System.out.println("Thank you for your generous donation of $" + value);

Hayır, bu iyi kokmuyor. Mükemmel bir dünyada Donationsoyut bir yöntem olacaktı getValueve her uygulama alt tipi uygun bir uygulamaya sahip olacaktı.

Peki ya bu sınıflar kütüphaneden geliyorsa, değiştiremezsiniz veya değiştirmek istemezseniz? O zaman başka bir seçenek yok.


Bu, ziyaretçi kalıbını kullanmak için iyi bir zaman gibi görünüyor. Veya dynamicaynı sonucu veren anahtar kelime.
user2023861

3
@ user2023861 Hayır Ziyaretçi modelinin Bağış alt sınıflarından işbirliğine dayandığını düşünüyorum - yani Bağış'ın void accept(IDonationVisitor visitor)alt sınıflarının belirli (örneğin aşırı yüklenmiş) yöntemlerini çağırarak uyguladıkları bir özet beyan etmesi gerekir IDonationVisitor.
ChrisW

@ ChrisW, bu konuda haklısın. İşbirliği olmadan, yine de dynamicanahtar kelimeyi kullanarak yapabilirsiniz .
user2023861

Bu özel durumda Bağış için bir tahminValue yöntemi ekleyebilirsiniz.
user253751

@ user2023861: dynamichala yavaşlayan, sadece daha yavaş.
Mehrdad

12

Yorum yazamadığımdan beri Eric Lippert'in cevabını eklemek için ...

Generikleri kullanmak için bir API'yi yeniden gözden geçirerek sık sık aşağıya düşmeyi önleyebilirsiniz. Ancak jenerikler, 2.0 sürümüne kadar dile eklenmedi . Bu nedenle, kendi kodunuzun eski dil sürümlerini desteklemesi gerekmese bile, kendinizi parametrelendirilmemiş eski sınıfları kullanarak bulabilirsiniz. Örneğin, bazı sınıflar, Objectgerçekte bildiğiniz türe basmak zorunda kaldığınız bir tür yük taşıyacak şekilde tanımlanabilir .


Gerçekten de, biri Java veya C # 'daki jeneriklerin, elementleri tekrar kullanmadan önce süper sınıf nesnelerin saklanması ve doğru (derleyici tarafından kontrol edilen) alt sınıfına aşağı doğru indirilmesinde sadece güvenli bir sarıcı olduğunu söyleyebilir. (Her zaman bu şekilde bir alt sınıfı, kendisini kullanmak için bir kod yeniden C ++ şablonları, farklı Downcast zorunda kalmamak - genellikle eğer derleme zamanında ve çalıştırılabilir boyutta pahasına, bellek performansını artırabilir.)
leftaroundabout

4

Statik ve dinamik olarak yazılmış diller arasında bir denge vardır. Statik yazım, derleyiciye, programların (bazı bölümlerinin) güvenliği hakkında oldukça güçlü garanti verebilecek birçok bilgi verir. Ancak bunun bir bedeli var çünkü programınızın doğru olduğunu bilmeniz gerekmez, aynı zamanda derleyiciyi bu durumda olduğuna ikna etmek için uygun kodu yazmanız gerekir. Başka bir deyişle, iddiada bulunmak, kanıtlamaktan daha kolaydır.

Derleyiciye kanıtlanamayan iddialarda bulunmanıza yardımcı olacak "güvensiz" yapılar vardır . Örneğin, şartsız çağrılar Nullable.Value, koşulsuz downcasts, dynamicvb nesneler, Onlar bir iddiada izin ( "Ben bu nesne iddia abir olduğunu Stringyanılıyorsam, atmak bir InvalidCastException") olmadan bunu kanıtlamak gerek. Bu, kanıtlamanın değerliden daha zor olduğu durumlarda faydalı olabilir.

Bunu kötüye kullanmak risklidir, bu nedenle açık downcast gösterimi var ve zorunludur; öyle sözdizimsel tuz güvenli olmayan bir operasyonda dikkat çekmek içindir. Dil , örtük aşağı yayınlama ile uygulanmış olabilir (çıkarılan türün açık olmadığı durumlarda), ancak bu güvenli olmayan işlemi gizler, ki bu arzu edilmez.


Sanırım, bu tür bir "kanıtlanmamış iddiayı" yapmak için gereken / istendiğinde (yani iyi uygulama) nerede / ne zamandan bazı örnekler soruyorum.
ChrisW

1
Bir yansıtma işleminin sonucunu atmaya ne dersiniz? stackoverflow.com/a/3255716/3141234
Alexander

3

Downcasting birkaç nedenden dolayı kötü olarak kabul edilir. Öncelikle düşünüyorum çünkü bu anti-OOP.

OOP, '' raison-d'etre '' olarak asla hayal kırıklığına uğratmak zorunda kalmazsanız, gerçekten hoşuna gider, polimorfizmin gitmek zorunda olmadığınız anlamına gelir.

if(object is X)
{
    //do the thing we do with X's
}
else
{
    //of the thing we do with Y's
}

sadece yap

x.DoThing()

ve kod otomatik olarak doğru olanı yapar.

Havaya uçmamak için bazı 'zor' sebepler var:

  • C ++ 'da yavaştır.
  • Yanlış tipi seçerseniz çalışma zamanı hatası alırsınız.

Ancak, bazı senaryolarda yer alan uydudan yayınlamaya alternatif oldukça çirkin olabilir.

Klasik örnek, işleme işlevini nesneye eklemek istemediğiniz ancak mesaj işlemcisinde saklamak istemediğiniz mesaj işlemesidir. Daha sonra MessageBaseClassişlemek için bir dizi ton var , ancak aynı zamanda doğru işleme için alt tip her birine ihtiyacım var.

Problemi çözmek için Double Dispatch'i kullanabilirsiniz ( https://en.wikipedia.org/wiki/Double_dispatch ) ... Ama bunun da sorunları var. Ya da bu zor nedenlerle risk altında basit bir kod için sadece downcast yapabilirsiniz.

Fakat bu Jeneriklerin icat edilmesinden önceydi. Artık ayrıntıların daha sonra belirtildiği bir tür sağlayarak aşağıya doğru yayılmasını önleyebilirsiniz.

MessageProccesor<T> yöntem parametrelerini değiştirebilir ve değerleri belirtilen türe göre değiştirebilir ancak yine de genel işlevsellik sağlayabilir

Elbette hiç kimse sizi OOP kodu yazmaya zorlamıyor ve yansıma gibi sağlanan ancak kaşlarını çattığınız birçok dil özelliği var.


1
C ++ 'da yavaş olduğundan şüpheliyim, özellikle static_castde dynamic_cast.
ChrisW

"Mesaj işleme" - Bunun, örneğin lParambelirli bir şeye atıfta bulunmak anlamına geldiğini düşünüyorum . Bunun iyi bir C # örneği olduğundan emin değilim.
ChrisW

3
@ChrisW - evet, evet, static_casther zaman hızlıdır ... ama bir hata yaparsanız tanımsız şekillerde başarısız değil garanti edilmez ve tip değil beklediğiniz buysa.
Jules

@Jules: Bu tamamen meselenin yanında.
Mehrdad

@Mehrdad, tam olarak mesele. Eşdeğer c # yapmak için c ++ c yavaştır. ve bu, alçıya karşı geleneksel sebep. Alternatif static_cast eşdeğer değildir ve tanımsız davranış nedeniyle daha kötü bir seçenek olarak kabul edilir
Ewan

0

Daha önce söylenenlere ek olarak, type nesnesine ait bir Tag özelliğini hayal edin. İstediğiniz nesneyi daha sonra kullanmak için başka bir nesnede saklamanız için bir yol sağlar. Bu özellik için aşağıya ihtiyacınız var.

Genel olarak, bugüne kadar bir şey kullanmamak her zaman işe yaramaz bir şeyin göstergesi değildir ;-)


Evet, bkz. Örneğin .net'teki Tag özelliği nedir . Buradaki cevaplardan birinde, birileri yazdı, bunu Windows Forms uygulamalarında kullanıcıya talimat girmek için kullanırdım. Kontrol GotFocus olayı tetiklendiğinde, Label.Text özelliğine komutlar, komut dizesini içeren kontrol Etiketi özelliğimin değerine atandı. Sanırım Control( object Tagözellik kullanmak yerine) genişletmek için alternatif bir yol, Dictionary<Control, string>her bir kontrolün etiketini saklamak için bir tane oluşturmak olacaktır .
ChrisW

1
Bu cevabı beğendim çünkü Tag.net framework sınıfının halka açık bir mülküdür, ki bunu kullanmanız gerektiğini (az ya da çok) olduğunu gösterir.
ChrisW

@ChrisW: sonuç yanlıştır (veya sağ) demek değil, ama orada kamu .NET işlevselliği bol olduğu için, bu özensiz muhakeme olduğunu unutmayın olan eskimiş (diyelim ki, System.Collections.ArrayList) ya da başka şekilde (diyelim ki, kullanımdan kaldırıldı IEnumerator.Reset).
Mehrdad

0

İşimde aşağıya akmanın en yaygın kullanımı, Liskov'un Yerine Getirilmesi ilkesini bozan bir salak yüzünden.

Bazı üçüncü taraf kütüphanelerinde bir arayüz olduğunu hayal edin.

public interface Foo
{
     void SayHello();
     void SayGoodbye();
 }

Ve onu uygulayan 2 sınıf. Barve Qux. Bariyi davrandı.

public class Bar
{
    void SayHello()
    {
        Console.WriteLine(“Bar says hello.”);
    }
    void SayGoodbye()
    {
         Console.WriteLine(“Bar says goodbye”);
    }
}

Ama Quxiyi davranılmamış.

public class Qux
{
    void SayHello()
    {
        Console.WriteLine(“Qux says hello.”);
    }
    void SayGoodbye()
    {
        throw new NotImplementedException();
    }
}

Şey ... şimdi başka bir seçeneğim yok. Ben var benim program bir çökmesini durma noktasına geldi zorunda kalmamak için onay ve (muhtemelen) mahzun yazın.


1
Bu özel örnek için doğru değil. SayGoodbye'ı çağırırken sadece NotImplementedException'ı yakalayabilirsiniz.
Zweigbergk Per

Bu aşırı derecede basitleştirilmiş bir örnek olabilir, ancak biraz daha eski .Net API'leri ile çalışın ve bu duruma gireceksiniz. Bazen kodu yazmanın en kolay yolu, güvenli bir şekilde ala ala güvenli yapmaktır var qux = foo as Qux;.
RubberDuck

0

Başka bir gerçek dünya örneği WPF'ler VisualTreeHelper. Bu döküm için mahzun kullanır DependencyObjectetmek Visualve Visual3D. Örneğin, VisualTreeHelper.GetParent . Downcast VisualTreeUtils.AsVisualHelper içinde gerçekleşir :

private static bool AsVisualHelper(DependencyObject element, out Visual visual, out Visual3D visual3D)
{
    Visual elementAsVisual = element as Visual;

    if (elementAsVisual != null)
    {
        visual = elementAsVisual;
        visual3D = null;
        return true;
    }

    Visual3D elementAsVisual3D = element as Visual3D;

    if (elementAsVisual3D != null)
    {
        visual = null;
        visual3D = elementAsVisual3D;
        return true;
    }            

    visual = null;
    visual3D = null;
    return false;
}
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.