Yeni nesneye atarken anahtar veya Sözlük


12

Son zamanlarda, ifadeler Dictionariesyerine 1-1 ilişkilerini eşlemeyi tercih ettim Switch. Yazmanın biraz daha hızlı ve zihinsel olarak işlenmesinin daha kolay olduğunu düşünüyorum. Ne yazık ki, bir nesnenin yeni bir örneğiyle eşlerken, bunu şu şekilde tanımlamak istemiyorum:

var fooDict = new Dictionary<int, IBigObject>()
{
    { 0, new Foo() }, // Creates an instance of Foo
    { 1, new Bar() }, // Creates an instance of Bar
    { 2, new Baz() }  // Creates an instance of Baz
}

var quux = fooDict[0]; // quux references Foo

Bu yapı göz önüne alındığında, CPU döngülerini ve belleklerini 3 nesne oluşturarak, kurucularının içerebileceği her şeyi yaptım ve sadece bunlardan birini kullanarak boşa harcadım. Ayrıca fooDict[0], bu durumda diğer nesnelerin eşlenmesinin Foo, amaçlandığı gibi yeni bir örnek oluşturmak yerine, aynı şeye başvurmalarına neden olacağına inanıyorum . Bunun yerine bir çözüm lambda kullanmak olacaktır:

var fooDict = new Dictionary<int, Func<IBigObject>>()
{
    { 0, () => new Foo() }, // Returns a new instance of Foo when invoked
    { 1, () => new Bar() }, // Ditto Bar
    { 2, () => new Baz() }  // Ditto Baz
}

var quux = fooDict[0](); // equivalent to saying 'var quux = new Foo();'

Bu çok kafa karıştırıcı bir noktaya mı geliyor? Sonunda bunu kaçırmak kolaydır (). Yoksa bir işleve / ifadeye eşleme yapmak oldukça yaygın bir uygulama mıdır? Alternatif bir anahtar kullanmak olacaktır:

IBigObject quux;
switch(someInt)
{
    case 0: quux = new Foo(); break;
    case 1: quux = new Bar(); break;
    case 2: quux = new Baz(); break;
}

Hangi çağırma daha kabul edilebilir?

  • Daha hızlı aramalar ve daha az anahtar kelime için (büyük / küçük harf) sözlük
  • Anahtar: Kodda daha yaygın olarak bulunan, dolaylı olarak bir Func <> nesnesinin kullanılmasını gerektirmez.

2
lambda olmadan, her aramayı aynı anahtarla yaptığınızda (olduğu gibi fooDict[0] is fooDict[0]) aynı örneğe sahip olursunuz . hem lambda hem de anahtar ile durum böyle değil
cırcır ucube

@ratchetfreak Evet, aslında örneği yazarken bunu fark ettim. Sanırım bir yere not ettim.
KChaloux

1
Açıkça bir Sabit'e koymuş olmanız, yaratılan nesnenin değişebilir olması gerektiği anlamına geliyor. Ancak bir gün onları değişmez hale getirebilirseniz, nesneyi doğrudan döndürmek en iyi çözüm olacaktır. Bir sabit alana diksiyonu koyabilir ve tüm uygulamada yalnızca bir kez oluşturma maliyetine katlanabilirsiniz.
Laurent Bourgault-Roy

Yanıtlar:


7

Bu fabrika modeline ilginç bir bakış . Sözlük ve lambda ifadesinin kombinasyonunu seviyorum; o konteynere yeni bir şekilde bakmamı sağladı.

Lamda olmayan yaklaşımın ihtiyacınız olanı sağlamadığı yorumlarında belirttiğiniz gibi CPU döngüleri hakkındaki sorunuzdaki endişeyi görmezden geliyorum.

Bence her iki yaklaşım da (Switch + Dictionary + lambda'ya karşı) iyi olacak. Tek sınırlama, Dictionary'i kullanarak, döndürülen sınıfı oluşturmak için alabileceğiniz girdi türlerini sınırlamanızdır.

Bir switch deyimi kullanmak, giriş parametreleri üzerinde daha fazla esneklik sağlar. Ancak, bu bir sorun olması gerekiyorsa, sözlüğü bir yöntemin içine sarabilir ve aynı sonucu elde edebilirsiniz.

Ekibiniz için yeniyse, kodu yorumlayın ve neler olduğunu açıklayın. Bir takım kodu incelemesi için çağrı yapın, yapılanlar arasında gezinin ve farkında olun. Bunun dışında iyi görünüyor.


Ne yazık ki, yaklaşık bir ay önce, ekibim sadece benden oluşuyor. Fabrika modeliyle ilgisini düşünmedim. Aslında bu düzgün bir gözlem.
KChaloux

1
@KChaloux: Tabii ki, sadece Fabrika Metodu desenini kullanıyorsanız, yazmanız çok kolay ve okunması çok daha kolay case 0: quux = new Foo(); break;hale gelircase 0: return new Foo();{ 0, () => new Foo() }
pdr

@pdr Bu kodda zaten birkaç yer var. Bu soruya ilham veren nesne üzerinde bir fabrika yöntemi oluşturmak için muhtemelen iyi bir neden var, ancak kendi başına sormanın yeterince ilginç olduğunu düşündüm.
KChaloux

1
@KChaloux: Ben itiraf ediyorum son takıntı anahtar / vaka yerine bir sözlük ile değiştirme meraklı değilim. Anahtarı kendi yönteminde basitleştirmenin ve izole etmenin daha etkili olmayacağı bir dava görmedim.
pdr

@pdr Obsession burada kullanmak için güçlü bir kelimedir. Değerler arasında bir kerelik eşlemelerle nasıl başa çıkılacağına karar verirken daha fazla dikkat edilmesi gereken nokta. Tekrarlanan durumlarda, yaratıcı bir yöntemi izole etmenin en iyisi olduğunu kabul ediyorum.
KChaloux

7

C # 4.0, Lazy<T>kendi ikinci çözümünüze benzer bir sınıf verir , ancak "Tembel başlatma" yı daha açık bir şekilde bağırır.

var fooDict = new Dictionary<int, Lazy<IBigObject>>()
{
    { 0, new Lazy(() => new Foo()) }, // Returns a new instance of Foo when invoked
    { 1, new Lazy(() => new Bar()) }, // Ditto Bar
    { 2, new Lazy(() => new Baz()) }  // Ditto Baz
}

Ooh, bilmiyordum.
KChaloux

Oh, bu güzel!
Laurent Bourgault-Roy

2
Ancak, bir kez Lazy.Value çağrıldığında, yaşamı boyunca aynı örneği kullanır. Bkz Tembel Başlatma
Dan Lyons

Tabii ki, aksi takdirde tembel başlatma olmaz, her seferinde yeniden başlatma olur.
Avner Shahar-Kashtan

OP her seferinde yeni örnekler yaratmak için ona ihtiyaç duyduğunu belirtir. Lambdas ile ikinci çözüm ve bir anahtar ile üçüncü çözüm bunu yaparken, ilk çözüm ve Lazy <T> uygulaması bunu yapmaz.
Dan Lyons

2

Stilistik olarak okunabilirliğin aralarında eşit olduğunu düşünüyorum. İle bağımlılık enjeksiyonu yapmak daha kolaydır Dictionary.

Kullanırken anahtarın var olup olmadığını kontrol etmenizi ve yoksa Dictionarygeri dönüş sağlamasını unutmayın.

switchStatik kod yolları ve Dictionarydinamik kod yolları (burada ekleyebilir veya kaldırabilirsiniz) deyimini tercih ederim . Derleyici ile bazı statik optimizasyonlar için mümkün olabilir switcho ile bunu yapamazsınız Dictionary.

İlginçtir, bu Dictionarydesen insanların bazen Python'da yaptıklarıdır, çünkü Python switchifadeden yoksundur . Aksi takdirde if-else zincirlerini kullanırlar.


1

Genel olarak, ikisini de tercih etmem.

Ne tüketiyorsa bunu yapmalı Func<int, IBigObject>. Ardından eşlemenizin kaynağı bir Sözlük veya bir anahtar deyimi veya bir web hizmeti çağrısı veya bir dosya araması olan bir yöntem olabilir ... her neyse.

Uygulamaya gelince, sözlüğü daha kolay 'sabit kod sözlüğü, arama anahtarı, sonuç döndür' den 'dosyadan sözlüğe yükleme, arama anahtarı, sonuç döndür' den daha kolay tercih ederim.

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.