Ne zaman C # örtük türü dönüştürme operatörü kullanmalıyım?


14

C # 'da, örtük dönüşüm operatörünü şu şekilde aşırı yükleyebiliriz ( MSDN'den örnek ):

struct Digit
{
    /* ... */
    public static implicit operator byte(Digit d)  // implicit digit to byte conversion operator
    {
        /* ... */
    }
}

Böylece, bir tipi, bir olabilir özel değer türü , sihirli (kulis akran ve kapalı dönüştürme operatörü görene kadar olduğu), şaşkınlık izleyici bırakarak bir (alakasız) tipine kendini dönüştürülmesi.

Şaşkınlıkla kodumu okuyan hiç kimseyi terk etmekten hoşlanmıyorum. Pek çok insanın olduğunu sanmıyorum.

Soru, kodumu anlamak için çok daha zor hale getirmeyen örtük tip dönüşüm operatörünün kullanım durumları nelerdir?


1
Vay. Aslında bunun var olduğunu bilmiyordum. Kullanmak için iyi bir şey olduğu anlamına gelmez; İnsanların C ++ 'da bu tür işlevsellik gizleme konusunda gerçekten rahatsız olduklarını biliyorum.
Katana314

@ Katana314: İnsanların rahatsız olduğu şey değildi, ama şaşırtıcı bir davranışla, tercihen ustaca şaşırtıcı olan bir aşırı yük (operatör, dönüşüm fonksiyonu, kurucu, serbest fonksiyon veya üye fonksiyonu) ekleyen biri hakkında.
Tekilleştirici

C ++ 'da "operatör aşırı yüklenmesi", özellikle "döküm" operatörlerini okumanızı tavsiye ederim. Tartışmak için C # var çok daha fazlası ile üç kez devam dışında tek argüman / karşı aynı argümanların çoğunun aynı olduğundan şüpheleniyorum.

Yanıtlar:


18

Yalnızca kabaca aynı değerleri farklı şekillerde temsil eden türler arasında örtük dönüşümler öneririm. Örneğin:

  • Farklı renk çeşitleri gibi RGB, HSL, HSVve CMYK.
  • Aynı fiziksel miktar için farklı birimler ( Metervs Inch).
  • Farklı koordinat sistemleri (polar ve Kartezyen).

Ancak, bunu gösterecek bazı güçlü kurallar vardır değil bir örtük dönüştürme tanımlamak mülk:

  • Dönüşüm önemli bir hassasiyet veya aralık kaybına neden oluyorsa, o zaman örtük olmamalıdır (örn: float64'ten float32'ye veya uzuntan int'e).
  • Dönüşüm bir ( InvalidCast) istisnası fırlatabilirse , örtük olmamalıdır.
  • Dönüştürme, her gerçekleştirildiğinde yığın ayırmaya neden oluyorsa, örtük olmamalıdır.
  • Dönüştürme bir O(1)işlem değilse, örtük olmamalıdır.
  • Kaynak türü veya hedef türü değiştirilebilirse, dönüşüm örtük olmamalıdır.
  • Dönüşüm bir tür içeriğe (veritabanı, kültür ayarları, yapılandırma, dosya sistemi vb.) Bağlıysa, o zaman örtük olmamalıdır (bu durumda açık bir dönüştürme operatörünü de caydırırım).

Şimdi dönüşüm operatörünüzün f: T1 -> T2yukarıdaki kurallardan herhangi birini ihlal etmediğini, ardından aşağıdaki davranışın dönüşümün örtük olabileceğini güçlü bir şekilde gösterdiğini varsayalım:

  • Eğer a == böyleyse f(a) == f(b).
  • Eğer a != böyleyse f(a) != f(b).
  • Eğer a.ToString() == b.ToString()öyleyse f(a).ToString() == f(b).ToString().
  • Hem T1ve hem de T2.

Tüm örnekleriniz muhtemelen kayıplıdır. Yine de yeterince kesin olsunlar, ...
Tekilleştirici

Evet bunu anladım :-). "Kayıplı" için daha iyi bir terim düşünemedim. "Kayıplı" ile kastettiğim, aralık veya hassasiyetin önemli ölçüde azaldığı dönüşümlerdir. Örneğin float64'ten float32'ye veya uzuntan int'e.
Elian Ebbing

Bence! = B => f (a)! = F (b), muhtemelen uygulanmamalıdır. Farklı girişler, floor () ve ceil () için aynı değeri döndürebilen birçok işlev vardır, örneğin matematik tarafında
cdkMoose 20:15

@cdkMoose Tabii ki haklısınız, bu yüzden bu özellikleri kurallar olarak değil, "bonus puanlar" olarak görüyorum. İkinci özellik, dönüştürme işlevinin yerinde olmadığı anlamına gelir. Genellikle int32'den int64'e kadar daha geniş bir aralığı olan bir türe dönüştürdüğünüzde bu durum söz konusudur.
Elian Ebbing

@cdkMoose Öte yandan, birinci özellik sadece aynı eşdeğerlik sınıfı T1( ==ilişkisiyle ima edilir T1) içindeki iki değerin her zaman aynı eşdeğerlik sınıfı içindeki iki değere eşlendiğini belirtir T2. Şimdi düşünüyorum, ilk özellik aslında örtük bir dönüşüm için gerekli olması gerektiğini düşünüyorum.
Elian Ebbing

6

Soru, kodumu anlamak için çok daha zor hale getirmeyen örtük tip dönüşüm operatörünün kullanım durumları nelerdir?

Türleri zaman değil (programcılar için) bir ilgisi yoktur. Aslında ilişkili olan (etki alanı veya makul programcılar için) iki ilişkisiz türün (kod söz konusu olduğunda) olduğu (nadir) senaryolar vardır.

Örneğin, dize eşleştirmesi yapmak için bazı kodlar. Yaygın bir senaryo, bir dize değişmez değeriyle eşleşmektir. Aramak yerine IsMatch(input, new Literal("some string")), örtük bir dönüşüm bu törenden - koddaki gürültüden - kurtulmanıza ve dizgi değişmezine odaklanmanıza izin verir.

Çoğu programcı IsMatch(input, "some string")neler olup bittiğini hızla görecek ve sezecektir. Arama sitesinde kodunuzu daha net hale getirir. Kısacası, biraz daha kapsamlı hale getirir neyi hafif bir pahasına, oluyor nasıl o oluyor.

Şimdi, aynı şeyi yapmak için basit bir fonksiyon aşırı yükünün daha iyi olacağını iddia edebilirsiniz. Ve budur. Ancak bu tür bir şey her yerde mevcutsa, bir dönüştürmeye sahip olmak, aşırı işlev yükleri yığını yapmaktan daha temizdir (daha az kod, tutarlılık artar).

Ve programcıların ara türünü açıkça oluşturmalarını istemenin daha iyi olduğunu ve böylece "gerçekten neler olduğunu" görmelerini sağlayabilirsiniz. Bu daha az açıktır. Şahsen, gerçek dize eşleme örneğinin "gerçekten neler olup bittiğiyle ilgili" çok açık olduğunu düşünüyorum - programcının her şeyin nasıl gerçekleştiğinin mekaniğini bilmesine gerek yok . Tüm kodunuzun, kodunuzun üzerinde çalıştığı çeşitli işlemciler tarafından nasıl yürütüldüğünü biliyor musunuz? Programcıların bir şeyin nasıl işlediğini umursamayı bıraktıkları bir soyutlama çizgisi vardır . Örtük dönüşüm adımlarının önemli olduğunu düşünüyorsanız, örtük dönüşümü kullanmayın. Bilgisayarı mutlu etmek için tören olduklarını düşünüyorsanız ve programcı bu gürültüyü her yerde görmemek daha iyi olurdu,


Son noktanız daha da ileriye götürülebilir ve daha da ileri götürülmelidir: Bir programcının ötesinde bir şeyin nasıl yapıldığını umursamayacağı kadar iyi bir çizgi de vardır, çünkü bu sözleşmeye bağlı değildir.
Tekilleştirici
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.