Genel olarak C # veya .NET Framework'teki en büyük tasarım kusurlarından bazıları nelerdir?
Örnek: boş değer atanamaz bir dize türü yoktur ve bir IDataReader'dan değerleri alırken DBNull'u kontrol etmeniz gerekir.
Genel olarak C # veya .NET Framework'teki en büyük tasarım kusurlarından bazıları nelerdir?
Örnek: boş değer atanamaz bir dize türü yoktur ve bir IDataReader'dan değerleri alırken DBNull'u kontrol etmeniz gerekir.
Yanıtlar:
Bu gönderiye kesinlikle katılıyorum (ToString eksikliğini dışlayanlar için, sınıfınız için özel bir format sağlamak için bir hata ayıklayıcı özelliği vardır).
Yukarıdaki listenin üstüne, aşağıdaki makul istekleri de eklerim:
T : new(string)veya neredeT : new(string, int)var e = new Foo(); e { Bar = baz };Either<T>" gibi verimli bir kapalı cebirsel tip değildir, bu nedenle kapalı bir cebirsel tip beyan etmenin ve üzerinde kapsamlı desen eşleştirmesinin uygulanmasının bir yolunu çok isterim (temelde ziyaretçi modeli için birinci sınıf destek, ancak çok daha verimli); bu nedenle yalnızca numaralandırmaları alın, kapsamlı kalıp eşleştirme desteğiyle genişletin ve geçersiz vakalaraSystem.IOSınıfların Streambiraz kötü tasarlandığına dair başka bir gönderiye katılıyorum ; bazı uygulamaların atılmasını gerektiren herhangi bir arayüz NotSupportedExceptionkötü bir tasarımdır,IListolduğundan çok daha basit olmalı; aslında, bu gibi beton toplama arayüzleri çoğu için doğru olabilir ICollection,INotifyPropertyChangedalan adını bir dizge olarak alan gibi arabirimler için alan ve üye adlarını güvenli bir şekilde yansıtmanın bir yolunu sağlar ; Bunu, lambda'yı a MemberExpression, ie ile alan bir genişletme yöntemi kullanarak yapabilirsiniz . () => Foo, ancak bu çok verimli değil
nameof(), tek üye adları için işleci ekledi , ancak jeneriklerde çalışmıyor ( nameof(T) == "T"gerçek tür bağımsız değişkeninin adı yerine: yine de yapmanız gerekiyor typeof(T).Name) - ne de bir "yol" dizesi almanıza izin vermiyor , örneğin nameof(this.ComplexProperty.Value) == "Value"olası uygulamalarını sınırlama.IArithmetic; diğer kullanışlı paylaşımlı operatör arayüzleri de mümkündür,readonlyanahtar kelimesine sahipken ve C # 6.0 salt okunur otomatik özellikler eklerken, değişmez türler ve değerler için gerçek dil desteği kadar katı değildir.Sanırım şimdilik bu kadar yeter. Bunların hepsi geçen hafta karşılaştığım rahatsızlıklar. Gerçekten aklımı koyarsam muhtemelen saatlerce devam edebilirim. C # 4.0 zaten kesinlikle onayladığım adlandırılmış, isteğe bağlı ve varsayılan bağımsız değişkenler ekliyor.
Şimdi mantıksız bir istek için:
Güzel lütfen? :-)
List<T>bir milyon T'ye sahibim . Anlık görüntünün verimli bir şekilde çekilmesini nasıl önerirsiniz? # 21: readonly.... anahtar kelimesini kullanın, burada bazı iyi öneriler varken, bunlar çoğunlukla sadece önerilerdir, tasarım kusurları değil.
Reset()üzerinde yöntem IEnumerator<T>yineleyici blokları, dilin Spec için bile bir hata (idi talepler bu bir istisna atar)IEnumerable<out T>ve Func<in T, out TResult>ancak somut türler (gibi List<T>) değil.ApplicationException yerine gözden düştü - bu bir hata mıydı?Containsdaha sonraAdd ), bu nedenle farklı işlemleri senkronize eden bir koleksiyon o kadar da kullanışlı olmaz
System.Collections.ConcurrentTryAddGetOrAddTryRemoveusing/ lockşablonundan daha fazla yararlanılabilirdi - belki de yeniden kullanılabilir (genişletilebilir?) bir sözdizimini paylaşmalarına izin verebilirdi; bunu geri dönerek IDisposableve kullanarak simüle edebilirsiniz using, ancak daha net olabilirdiFoo(SqlConnection! connection)(boş bir kontrol / ekleyen throw) güzel olurdu ( int?vb. Aksine )
dynamicya da etkinleştirebilirsiniz böyleforeach, yani anon-methodlar / lambdas, her yineleme için bir değişken yerine tek bir değişkeni yakalar (threading / async / etc ile ağrılı)
ApplicationExceptionbir hata olduğunu söylediler - umdukları kadar yararlı değil. Bunun System.Exceptionolması gerektiğini de söylediler abstract.
TextWriter a, temel StreamWriter'ın sınıfıdır. o ne lan?
Bu her zaman beni aşırı derecede karıştırır.
Küçük bir C # pet peev - oluşturucular, oluşturucunun sınıfla aynı ada sahip olması için C ++ / Java sözdizimini kullanır.
New()ya ctor()da çok daha güzel olurdu.
Ve elbette, coderush gibi araçlar, sınıfları yeniden adlandırmak için bunu daha az sorun haline getirir, ancak okunabilirlik bakış açısıyla, New () büyük bir netlik sağlar.
class Foo { new(int j) {i = j} int i; }
New--uppercase olmayan anahtar kelimeler geleneğe aykırıdır), buna tasarım hatası demekten çekiniyorum. Mevcut C ++ / Java geliştiricilerini cezbetmek istediler ve birçok aptal eski sözdizimsel geleneği ödünç almak, muhtemelen hedeflerine ulaşmalarına yardımcı oldu.
Yapamayacağını anlamıyorum
burada T: yeni (U)
Yani genel tip T'nin varsayılan olmayan bir kurucuya sahip olduğunu bildirirsiniz.
Düzenle:
Bunu yapmak istiyorum:
public class A
{
public A(string text)
{
}
}
public class Gen<T> where T : new(string text)
{
}
Bundan ilk bahseden ben olduğuma gerçekten şaşırdım:
ADO.NET türlenmiş veri kümeleri, null yapılabilir türlerin özellikleri olarak null yapılabilir sütunları göstermez. Bunu yazabilmelisin:
int? i = myRec.Field;
myRec.Field = null;
Bunun yerine şunu yazmalısın ki bu çok aptalca:
int? i = (int?)myRec.IsFieldNull() ? (int?)null : myRec.Field;
myRec.SetFieldNull();
Bu, .NET 2.0'da can sıkıcıydı ve güzel, düzgün LINQ sorgularınızda yukarıdaki gibi jiggery-pokery kullanmak zorunda olmanız şimdi daha da can sıkıcı.
Ayrıca, üretilen Add<TableName>Rowyöntemin null atanabilir türler kavramına benzer şekilde duyarsız olması da can sıkıcı . Her şey, oluşturulduğundan beriTableAdapter yöntemler öyle değil.
.NET'te geliştirme ekibinin "Tamam çocuklar, yeterince yakınız - gönderin!" Dediğini hissettiren pek bir şey yok. Ama bu kesinlikle öyle.
DBNull.Valueolduğunda , özel bir değer talep etmenin saçmalığını unutmayalım null. Neyse ki LINQ-to-SQL sadece NULL için null kullanır.
Edit
5. Benim bir başka sıkıntım da System.Reflection.BindingFlags'ın kullandığınız yönteme bağlı olarak farklı kullanımları olmasıdır. Örneğin FindFields'da CreateInstance veya SetField ne anlama geliyor? Bu, kafa karıştırıcı olan bu sayımın arkasındaki anlamı aşırı yükledikleri bir durum.
Bunun bir tasarım hatası olduğunu söyleyecek kadar ileri gideceğimi bilmiyorum, ancak VB'de yapabildiğiniz gibi bir lambda ifadesini çıkarırsanız gerçekten güzel olurdu:
VB:
Dim a = Function(x) x * (x - 1)
C #
Bunu yapabilsem güzel olurdu:
var a = x => x * (x - 1);
Bunu yapmak zorunda kalmak yerine:
Func<int, int> a = x => x * (x - 1);
Çok uzun sürmediğinin farkındayım, ama Code Golf'te her karakterin önemi var! Bu programlama dillerini tasarlarken bunu hesaba katmıyorlar mı? :)
(int x) => x * (x -1);anlam ifade edebilir Func<int, int>veya şu anlama gelebilirExpression<Func<int, int>>
+için tanımlanmadığı için olamaz object.
System.Object sınıfı:
Eşittir ve GetHashCode - tüm sınıflar karşılaştırılabilir veya karma hale getirilemez, bir arabirime taşınmalıdır. IEquatable veya IComparable (veya benzeri) akla geliyor.
ToString - tüm sınıflar bir dizeye dönüştürülemez, bir arabirime taşınmalıdır. IFormattable (veya benzeri) akla geliyor.
ICollection.SyncRoot özelliği:
Jenerikler başından beri orada olmalıydı:
EqualityComparer<T>.Defaultdoğru şekilde güncellemektir . Sonra her ikisi de var dict = new Dictionary<object, string>(EqualityComparer<object>.Default)ve var dict = new Dictionary<object, string>()referans karşılaştırma / eşitlik kullanacaktır.
EqualityComparer<T>.Defaultyaradığıdır. Her aramada kontrol etmeye gerek yok. Karşılaştırıcı, Dictionaryörnek için bir özelliktir ve her Dictionarybiri hangisini kullandığını bilir.
Beni rahatsız eden şeylerden biri Predicate<T> != Func<T, bool>paradoks. İkisi de türden delege T -> boolama yine de atama uyumlu değiller.
Bazı insanlar (ISV'ler) dotNet çalışma zamanına ihtiyaç duymayan yerel bir yürütülebilir dosya oluşturmak için derleme zamanında makine koduna derleyebilmenizi ve onu bağlamanızı ister.
Doğru OO teknikleri hakkında çok şey biliyoruz . Ayrıştırma, sözleşmeyle programlama, uygunsuz kalıtımdan kaçınma, istisnaların uygun kullanımı, açık / kapalı yönetici, Liskov ikame edilebilirliği vb. Henüz hiçbiri, .Net çerçeveleri en iyi uygulamaları kullanmamaktadır.
Bana göre .Net tasarımındaki en büyük kusur, devlerin omuzlarında durmak değil; Çerçevelerini kullanan programcı kitlelerine ideal programlama paradigmalarından daha azını tanıtmak .
MS buna dikkat etseydi, yazılım mühendisliği dünyası bu on yılda kalite, kararlılık ve ölçeklenebilirlik açısından büyük sıçramalar yapabilirdi, ancak ne yazık ki geriliyor gibi görünüyor.
C # switch deyimini beğenmedim.
Bunun gibi bir şey isterim
switch (a) {
1 : do_something;
2 : do_something_else;
3,4 : do_something_different;
else : do_something_weird;
}
Böylece artık kesintiler (unutulması kolay) ve farklı değerleri virgülle ayırma imkanı yok.
switchC'nin kasıtlı olarak sakatlanmış versiyonunu taklit eden tüm dillerde temelden kırılmıştır (hız için optimize edilmiştir!). VB çok daha iyi sonuç verir, ancak yine de kalıp eşleştirmeli dillerin (Haskell, F #…) ışık yılı geride kalmaktadır.
Dinleyicileri açıkça kontrol etmeniz gereken C # olayları. Olayların amacı, orada olanlara yayınlamak değil miydi? Hiç olmasa bile?
İç içe / yinelemeli yineleyicilerin korkunç (ve çoğu insan için oldukça görünmez) O (N ^ 2) davranışı .
Bu konuyu bildikleri, nasıl düzelteceklerini bildikleri için oldukça üzgünüm, ancak dahil olmayı hak etmek için yeterli önceliğe sahip olarak görülmüyor.
Her zaman ağaç benzeri yapılarla çalışıyorum ve aksi takdirde akıllı insanların kodunu, yanlışlıkla bu şekilde çok pahalı işlemler başlattıklarında düzeltmek zorundayım.
"Getiri foreach" in güzelliği, daha basit, daha kolay sözdiziminin doğru, performanslı kodu teşvik etmesidir. Bu, platformun uzun vadeli başarısı için yeni özellikler eklemeden önce hedeflemeleri gerektiğini düşündüğüm "başarı çukuru" dur.
Bazı sınıflar arabirimler uygular ancak bu arabirimin birçok yöntemini uygulamazlar, örneğin Array IList'i uygular ancak 9 yöntemden 4'ü NotSupportedException http://msdn.microsoft.com/en-us/library/system.array_members .aspx
Arabirimlerdeki statik üyeler ve iç içe geçmiş türler.
Bu, özellikle bir arayüz üyesi arayüze özgü bir parametreye ( örneğin, bir enum) sahip olduğunda faydalıdır . Numaralandırma türünü arabirim türüne yerleştirmek güzel olurdu.
Olayların son derece tehlikeli varsayılan doğası. Bir etkinliği arayabilmeniz ve kaldırılan aboneler nedeniyle tutarsız bir durumda olabilmeniz gerçekten korkunç. Bkz Jon Skeet en ve Eric Lippert en konuda daha fazla okuma için mükemmel makaleler.
null her yerde.
const Hiçbir yerde.
API'ler tutarsızdır, örneğin bir dizi dönüşünü mutasyona uğratmak, voidancak bir diziye eklemek StringBufferaynı değişebilir StringBuffer.
Toplama arayüzleri, değişmez veri yapılarıyla uyumsuzdur, örneğin Add, System.Collections.Generic.IList<_>bir sonuç döndüremez.
Yapısal yazım yok, bu yüzden System.Windows.Media.Effects.SamplingMode.Bilinearsadece yazmak yerine yazarsınız Bilinear.
Değişken IEnumeratorbir değişmez olması gerektiği zaman arayüz sınıfları tarafından uygulanan struct.
Eşitlik ve karşılaştırma bir karmaşa: Elinizdeki System.IComparableve Equalsancak o zaman da var System.IComparable<_>, System.IEquatable, System.Collections.IComparer, System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.Collections.Generic.IComparerve System.Collections.Generic.IEqualityComparer.
Tuplelar yapılar olmalıdır, ancak yapılar kuyruk çağrılarının ortadan kaldırılmasını gereksiz yere engeller, böylece en yaygın ve temel veri türlerinden biri gereksiz yere ayırır ve ölçeklenebilir paralelliği bozar.
IEnumerator?
0 enum olarak ayışığı
enum özellikleri: http://blogs.msdn.com/abhinaba/archive/2007/01/09/more-peculiarites-of-enum.aspx
bu iyi örnekte gösterildiği gibi: http://plus.kaist.ac.kr/~shoh/postgresql/Npgsql/apidocs/Npgsql.NpgsqlParameterCollection.Add_overload_3.html
benim önerim, "@" işaretini iyi bir şekilde kullanın:
onun yerine:
eğer ((myVar & MyEnumName.ColorRed)! = 0)
bunu kullan:
eğer ((myVar & MyEnumName.ColorRed)! = @ 0)
Başkaları tarafından zaten yapılmış olan uzun iyi noktalar listesine eklemek için:
DateTime.Now == DateTime.Now çoğu durumda, ancak her durumda değil.
StringDeğişmez olan, yapım ve manipülasyon için bir dizi seçeneğe sahiptir, ancak StringBuilder(değiştirilebilir olan) yoktur.
Monitor.Enterve Monitor.Exitörnek yöntemler olmalıydı, bu nedenle belirli bir nesneyi kilitlemek için yenileştirmek yerine, onu yenileyebilir Monitorve kilitleyebilirsiniz.
Yıkıcılar asla yıkıcı olarak adlandırılmamalıydı. ECMA spesifikasyonu, C ++ kalabalığı için çok daha az kafa karıştırıcı olan, bunlara sonlandırıcılar diyor, ancak dil spesifikasyonu hala onları yıkıcı olarak gösteriyor.
DateTime.NowBir geri kalanı için dünyanın en bariz yarış koşul, ancak 1 olduğunu
Özellikleri kullanma şeklimiz bazen beni rahatsız ediyor. Bunları Java'nın getFoo () ve setFoo () yöntemlerinin eşdeğeri olarak düşünmeyi seviyorum. Ama değiller.
Eğer Mülkiyet Kullanım Yönergeleri seri çalışabilir böylece özellikler gerekir devlet, herhangi bir sırada ayarlanması o zaman onlar sizsiniz, setter zamanlı doğrulama için yararsız. Bir nesnenin kendisinin geçersiz bir duruma geçmesine izin vermesini önlemek istediğiniz bir arka plandan geliyorsanız, özellikler sizin çözümünüz değildir. Bazen bu yüzden biz şeyin türden şeyler sınırlı yetkiye beri, kamu üyelerine daha iyi ne kadar görmek için başarısız gerekiyordu .
Bu amaçla, mülkiyet sözdizimini bir şekilde genişletebilmeyi her zaman diledim (bu çoğunlukla burada yüksek sesle düşünmektir, keşke böyle bir şey yapabilseydim). Bunun gibi bir şey hayal edin:
private string password;
public string Password
{
// Called when being set by a deserializer or a persistence
// framework
deserialize
{
// I could put some backward-compat hacks in here. Like
// weak passwords are grandfathered in without blowing up
this.password = value;
}
get
{
if (Thread.CurrentPrincipal.IsInRole("Administrator"))
{
return this.password;
}
else
{
throw new PermissionException();
}
}
set
{
if (MeetsPasswordRequirements(value))
{
throw new BlahException();
}
this.password = value;
}
serialize
{
return this.password;
}
}
Bunun yararlı olup olmadığından veya bunlara erişmenin nasıl görüneceğinden emin değilim. Ama keşke özelliklerle daha fazlasını yapabilmeyi ve onlara gerçekten get ve set yöntemleri gibi davranabilmeyi diliyorum.
Genişletme yöntemleri güzeldir, ancak mixins konusunda gerçek karışımlarla daha temiz bir şekilde çözülebilecek sorunları çözmenin çirkin bir yoludur (neden bahsettiğimi görmek için Ruby'ye bakın). Bunları dile eklemenin gerçekten güzel bir yolu, jeneriklerin kalıtım için kullanılmasına izin vermek olurdu. Bu, mevcut sınıfları güzel bir nesne yönelimli şekilde genişletmenize olanak tanır:
public class MyMixin<T> : T
{
// etc...
}
bu, örneğin bir dizeyi genişletmek için şu şekilde kullanılabilir:
var newMixin = new MyMixin<string>();
Uzatma yöntemlerinden çok daha güçlüdür çünkü yöntemleri geçersiz kılmanıza izin verir, örneğin bunları dil içinde AOP benzeri işlevselliğe izin verecek şekilde sarmalamak için.
Söz için özür dilerim :-)
Microsoft, çerçevedeki bariz hataları düzeltmeyecek ve son kullanıcıların bunları düzeltebilmesi için kancalar sağlamayacaktır.
Ayrıca, çalıştırılabilir .NET çalıştırılabilir dosyalarını çalışma zamanında ikili yama yapmanın bir yolu yoktur ve yerel kitaplıklara ikili yama uygulamadan (yükleme çağrısını kesmek için) .NET çerçeve kitaplıklarının özel sürümlerini belirtmenin bir yolu yoktur ve ILDASM yeniden dağıtılamaz, bu yüzden otomatikleştiremiyorum yine de yama.
Boş değişken üzerinde bir uzantı yöntemini çağırabilmek tartışılabilir örn.
nesne a = boş; a.MyExtMethod (); // bu çağrılabilir, bir yerde MyExtMethod'u tanımladığını varsayın
Kullanışlı olabilir, ancak boş referans istisna konularında belirsizdir.
Bir 'kusur' adlandırma. System.configuration.dll dosyasındaki "yapılandırma" nın 'C'si büyük harfle yazılmalıdır.
İstisna işleme. İstisna zorla yakalanmalı veya Java'da olduğu gibi fırlatılmalıdır, derleyici derleme zamanında kontrol etmelidir. Kullanıcılar, hedef çağrı içindeki istisna bilgileri için yorumlara güvenmemelidir.
Çerçevenin V1'indeki SqlCommand üzerindeki .Parameters.Add () yöntemi korkunç bir şekilde tasarlandı - 0 değerine (int) sahip bir parametreyi geçerseniz, aşırı yüklerden biri temelde çalışmazdı - bu onların yaratmasına yol açtı SqlCommand sınıfındaki .Parameters.AddWithValue () yöntemi.
ICollection<T>ve IList<T>; en azından, bir kovaryant salt okunur koleksiyon arayüzü IListSource<out T>(bir numaralandırıcı, indeksleyici ve Sayım ile) son derece yararlı olurdu.Transform(Sequence<T>, Func<T,T>) işlevin aynı değeri mi yoksa farklı bir değeri mi döndürdüğünü hızlı bir şekilde belirlemek için gereken işlevi . İşlev, argümanlarının çoğunu / tamamını değiştirmezse, çıktı dizisi giriş dizisindeki belleğin bir kısmını / tamamını paylaşabilir. Herhangi bir T tipini bit bazında karşılaştırma yeteneği olmadan, performansı muazzam derecede düşüren çok daha yavaş bir karşılaştırma kullanılmalıdır.List<T>bir varsayıma IListSource<U>(burada T: U) dönüştürme yapmanıza izin verirdi . Bu işlevselliği sağlamak için en az üç farklı kitaplık vardır (bağımsız olarak yazılır) (elbette performans dezavantajlarıyla birlikte - mükemmel bir çözüm mümkün olsaydı, bunu .NET'te bir kusur olarak adlandırmak adil olmazdı).WeakReference<T>(kendi yazınızı kolayca yazabilirsiniz, ancak dahili olarak dökümleri kullanacaktır.)Predicate<T>Vs Func<T,bool>) benim için rahatsızlık yarattı . Sıklıkla , bileşenler arasında daha gevşek bir bağlantı elde etmek için arabirimler ve temsilciler için yapısal tipleme yapabilmeyi diliyorum , çünkü .NET'te bağımsız DLL'lerdeki sınıfların aynı arabirimi uygulaması yeterli değildir - aynı zamanda üçüncü birine ortak bir referansı paylaşmaları gerekir Arayüzü tanımlayan DLL.DBNull.Valuenullaynı amaca eşit derecede iyi hizmet etmiş olsa bile vardır .variable = variable ?? value. Gerçekten de, C # 'da gereksiz yere simetriden yoksun olan birkaç yer vardır. Örneğin if (x) y(); else z();(parantez olmadan) yazabilirsiniz , ancak yazamazsınız try y(); finally z();.IList<T>ben kullanırım olsa IReadableByIndex<out T>ve IAppendable<in T>. Diğer şeylerin çoğu benim de aynı fikirde olduğum ciyaklamalar.
IListReader<T>;) - "kaynak" kelimesini "havuz" un zıttı olarak kullanıyorum (salt yazılır bir arayüz).
IListSource<in T>veya IReadableList<out T>. Temel arabirim türlerinin tüm türevlerde bulunmayan yöntemleri içermesinin değeri olabilir, ancak arabirimlerin bir şekilde özelleşmiş olmasının çoğu zaman iyi olduğunu düşünüyorum. Örneğin, IList<T>çalışabilecek veya çalışmayabilecek yeniden boyutlandırma yöntemlerini içeren IResizableList<T>ve aynı yöntemleri uygulayan, ancak bunların çalışması gerektiğini garanti eden bir tane olabilir. Böyle bir yaklaşım, bir alanın değişebilen bir listeye mevcut tek referansı veya değişmez bir listeye paylaşılan bir referansı içerdiği durumlarda faydalı olabilir.
if (rl:(list as IResizableList<T>) != null) rl.Add(...);, ancak başka öneriler de var. Çeşitli koleksiyonların ve koleksiyon adaptörlerinin yazarı olarak beni rahatsız eden şey, istisnalar atan pek çok kukla yöntem yazmak. Bir tür güvenlik hayranı olarak, yasadışı yöntemleri çağırmama izin verilmesini istemiyorum. Bir IntelliSense hayranı, bunların listelenmesini istemiyorum.
1.x'te beni işaretleyen bir şey System.Xml.XmlValidatingReader, ValidationEventHandler's' ler ValidationEventArgs, ve XmlSchemaExceptiongibi tüm yararlı bilgileri içeren temelini (dahili olarak işaretlenmiş) açığa çıkarmamasıydı . Bunun yerine, bunu Message string özelliğinden ayırmanız veya ortaya çıkarmak için yansıma kullanmanız beklenir. Son kullanıcıya daha temiz bir hata vermek istediğinizde o kadar iyi değil.linenumberposition
Bir numaralamanın değerlerini başka bir numaralandırmada kullanamamanız hoşunuza gitmiyor, örneğin:
enum Colors { white, blue, green, red, black, yellow }
enum SpecialColors { Colors.blue, Colors.red, Colors.Yellow }
typeof(Color)! = typeof(SpecialColors).
enum SpecialColors { blue = Colors.blue, red = Colors.red, yellow = Colors.Yellow }
Örtük olarak yazılan değişkenler kötü bir şekilde IMO olarak uygulanmıştır. Bunları gerçekten yalnızca Linq ifadeleriyle çalışırken kullanmanız gerektiğini biliyorum, ancak bunları yerel kapsamın dışında ilan edememeniz can sıkıcı.
MSDN'den:
Bunun zayıf bir uygulama olduğunu düşünmemin nedeni, ona var dedikleri, ancak bir varyant olmaktan çok uzak. Sınıf adını tam olarak yazmak zorunda kalmamak için gerçekten sadece kısa sözdizimidir (Linq ile kullanılması dışında)