C # Gizli Özellikleri? [kapalı]


1475

Bu sorudan aşağıdakileri öğrendikten sonra aklıma geldi :

where T : struct

Biz, C # geliştiricileri, hepimiz C # temellerini biliyoruz. Beyanlar, şartlar, döngüler, operatörler vb.

Bazılarımız Generics , anonim tipler , lambdas , LINQ , ...

Ancak C # hayranlarının, bağımlılarının, uzmanların bile zar zor bildiği en gizli özellikler veya C # numaraları nelerdir?

İşte şimdiye kadar ortaya çıkan özellikler:


Anahtar kelimeler

Öznitellikler

Sözdizimi

Dil özellikleri

Visual Studio Özellikleri

  • Himadri tarafından editördeki metin bloğunu seçin
  • Snippet'ler DannySmurf tarafından

iskelet

Yöntem ve Özellikleri

İpuçları & Hileler

  • Andreas HR Nilsson'un olay işleyicileri için güzel bir yöntem
  • John'un büyük harf karşılaştırmaları
  • Dp tarafından yansımasız anonim türlere erişin
  • Will tarafından toplama mülklerini tembel bir şekilde başlatmanın hızlı bir yolu
  • Roosteronacid'den JavaScript benzeri anonim satır içi işlevler

Diğer

Yanıtlar:


752

Bu C # değil, ama gerçekten System.IO.Path.Combine()gerektiği kadar kullanan kimseyi görmedim . Aslında, tüm Path sınıfı gerçekten yararlıdır, ancak hiç kimse bunu kullanmaz!

Olmasa bile, her üretim uygulamasının aşağıdaki kodu içerdiğine bahse girmeye hazırım:

string path = dir + "\\" + fileName;

584

lambdalar ve tür çıkarımları önemsizdir. Lambdas birden fazla ifadeye sahip olabilir ve otomatik olarak uyumlu bir delege nesnesi olarak ikiye katlanır (sadece imza eşleştiğinden emin olun):

Console.CancelKeyPress +=
    (sender, e) => {
        Console.WriteLine("CTRL+C detected!\n");
        e.Cancel = true;
    };

Unutmayın ve new CancellationEventHandlerne tür belirtmek zorunda değilim, senderve eonlar olaydan etkilenir. Bu nedenle, tüm delegate (blah blah)parametreleri yazmak için daha az kullanışlıdır ve bu da parametre türlerini belirtmenizi gerektirir.

Lambdas'ın bir şey döndürmesine gerek yoktur ve tür çıkarımı bu bağlamda son derece güçlüdür.

Ve BTW, her zaman Lambdas'ı işlevsel programlama anlamında yapan Lambdas'ı geri döndürebilirsiniz . Örneğin, bir Button'ı işleyen bir lambda yapan bir lambda.

Func<int, int, EventHandler> makeHandler =
    (dx, dy) => (sender, e) => {
        var btn = (Button) sender;
        btn.Top += dy;
        btn.Left += dx;
    };

btnUp.Click += makeHandler(0, -1);
btnDown.Click += makeHandler(0, 1);
btnLeft.Click += makeHandler(-1, 0);
btnRight.Click += makeHandler(1, 0);

Zincire dikkat edin: (dx, dy) => (sender, e) =>

İşte bu yüzden fonksiyonel programlama dersini almış olmaktan mutluluk duyuyorum :-)

C işaretçiler dışında, bence öğrenmeniz gereken diğer temel şey :-)


528

Gönderen Rick Strahl :

Zincir olabilir ?? bir dizi boş karşılaştırma yapabilmeniz için kullanılır.

string result = value1 ?? value2 ?? value3 ?? String.Empty;

454

Takma jenerikler:

using ASimpleName = Dictionary<string, Dictionary<string, List<string>>>;

Bunun ASimpleNameyerine kullanmanıza izin verir Dictionary<string, Dictionary<string, List<string>>>.

Birçok yerde aynı jenerik büyük uzun karmaşık şeyi kullanacağınız zaman kullanın.


438

Gönderen C # yoluyla CLR :

Dizeleri normalleştirirken, Microsoft büyük harfli karşılaştırmalar yapmak için kodu optimize ettiği için ToLowerInvariant yerine ToUpperInvariant kullanmanız önemle tavsiye edilir .

İş arkadaşımın karşılaştırma yapmadan önce her zaman dizeleri büyük harfe değiştirdiğini hatırlıyorum. Bunu neden yaptığını hep merak ettim çünkü önce küçük harfe dönüştürmenin daha "doğal" olduğunu hissediyorum. Şimdi kitabı okuduktan sonra nedenini biliyorum.


254
Bir dizeyi büyük harfe dönüştürdüğünüzde ikinci bir geçici dize nesnesi oluşturursunuz. Ben bu tür karşılaştırma tercih edilmediğini düşündüm, en iyi yolu: String.Equals (stringA, stringB, StringComparison.CurrentCultureIgnoreCase) olan bu atma dizesini hiç yaratmaz.
Anthony

32
Küçük harf dizelerinde yapılamayan büyük harf dizelerini karşılaştırırken ne tür bir optimizasyon yapabilirsiniz? Neden birinin diğerinden daha uygun olacağını anlamıyorum.
Parappa

36
Küçük harf yerine büyük harfe dönüştürmek de bazı kültürlerde yanlış davranışı önleyebilir. Örneğin, Türkçe olarak, iki küçük harf i aynı büyük harf I ile eşleşir. Daha fazla bilgi için Google "turkish i".
Neil

34
ToUpperInvariant ve ToLowerInvariant karşılaştırmasını denedim. .NET 2.0 veya 3.5 altında performanslarında herhangi bir fark bulamıyorum. Kesinlikle bir diğerinin üzerinde kullanarak "tavsiye" garanti hiçbir şey.
Rasmus Faber

19
ToUpperInvariant tercih edilir, çünkü tüm karakterleri gidiş-dönüş yapar. Bkz. Msdn.microsoft.com/en-us/library/bb386042.aspx . Karşılaştırma için, yazın"a".Equals("A", StringComparison.OrdinalIgnoreCase)
SLaks

408

En sevdiğim numara koleksiyonları otomatik olarak başlatmak için null birleştirme operatörü ve parantez kullanmak.

private IList<Foo> _foo;

public IList<Foo> ListOfFoo 
    { get { return _foo ?? (_foo = new List<Foo>()); } }

23
Okumak zor değil mi?
Riri

72
Noo, er, deneyimsiz okumak biraz zor. Ancak kompakttır ve programcının bilmesi ve anlaması gereken birkaç desen ve dil özelliği içerir. Bu yüzden, ilk başta zor olsa da, öğrenmenin bir nedeni olmanın faydasını sağlar.

38
Tembel örnekleme biraz yanlıştır çünkü sınıf değişmezleri hakkında düşünmekten kaçınmak kötü bir seçimdir. Aynı zamanda eşzamanlılık sorunları var.
John Leidegren

17
Her zaman bunun kötü bir uygulama olduğu, bir mülk çağırmanın böyle bir şey yapmaması gerektiği konusunda bilgilendirildim. Orada bir kümeniz varsa ve değeri null olarak ayarlarsanız, API'nızı kullanan biri için çok garip olur.
Ian

8
@ ListOfFoo öğesinin null değerine ayarlanması dışında ne dersiniz, ne sınıf sözleşmesinin bir parçası ne de iyi bir uygulamadır. Bu yüzden bir pasör yok. ListOfFoo'nun bir koleksiyonu döndürme garantisi vardır ve asla boş kalmaz. Onun sadece çok garip bir şikayet iki kötü şeyler (bir setter yapmak ve bir koleksiyon null olarak ayarlamak) yaparsanız, bu beklentilerinizi yanlış sonuçlanacaktır. Ben de alıcıda Environment.Exit () yapmayı önermem. Ama bunun da bu cevapla bir ilgisi yok.

315

Boş olay işleyicilerini denetlemekten kaçının

Beyan sırasındaki olaylara boş bir delege eklemek, olayı çağırmadan önce her zaman null olup olmadığını kontrol etme gereğini bastırmak harika. Misal:

public delegate void MyClickHandler(object sender, string myValue);
public event MyClickHandler Click = delegate {}; // add empty delegate!

Bunu yapmana izin ver

public void DoSomething()
{
    Click(this, "foo");
}

Bunun yerine

public void DoSomething()
{
    // Unnecessary!
    MyClickHandler click = Click;
    if (click != null) // Unnecessary! 
    {
        click(this, "foo");
    }
}

Lütfen bu konuyla ilgili ve Eric Lippert'in bu konudaki (ve olası dezavantajları) ilgili blog yayınına da bakın .


87
Bu tekniğe güvenir ve sonra sınıf serileştirmek zorunda kalırsanız bir sorun çıkacağına inanıyorum. Olayı ortadan kaldıracaksınız ve daha sonra serileştirme sırasında bir NullRefference alacaksınız. Bu daha guvenli.
sirrocco

16
yine de olay işleyicinizi null olarak ayarlayabilirsiniz, böylece yine de null referans alabilirsiniz ve yine de bir yarış durumunuz vardır.
Robert Paulson

64
Hızlı profil testi, boş testi olmayan kukla aboneli olay işleyicisinin, boş testi olmayan aboneliksiz işleyici süresinin yaklaşık 2 katı zaman aldığını gösterir. Boş testi olmayan çok noktaya yayın olay işleyicisi, boş test ile tekli olay işleyicisinin süresinin yaklaşık 3.5 katı sürer.
P Daddy

54
Bu her zaman kendi kendine abone olan bir null kontrol ihtiyacını ortadan kaldırır. Boş bir olay olarak bile, istemediğiniz bir yükü taşır. Etkinliği hiç tetiklemek istemediğiniz abone yoksa, her zaman önce boş bir sahte etkinlik tetiklemeyin. Bu kötü kodu düşünürdüm.
Keith

56
Yukarıdaki yorumlardaki nedenlerden dolayı bu korkunç bir öneri. Kodunuzun "temiz" görünmesi gerekiyorsa, null değerini kontrol etmek için bir uzantı yöntemi kullanın ve ardından etkinliği arayın. Değişiklik ayrıcalıklarına sahip bir kişi kesinlikle bu cevaba eksilerini eklemelidir.
Greg

305

Diğer her şey, artı

1) örtük jenerikler (neden sınıflar üzerinde değil, sadece yöntemler üzerinde?)

void GenericMethod<T>( T input ) { ... }

//Infer type, so
GenericMethod<int>(23); //You don't need the <>.
GenericMethod(23);      //Is enough.

2) bir parametre ile basit lambdas:

x => x.ToString() //simplify so many calls

3) isimsiz türler ve başlatıcılar:

//Duck-typed: works with any .Add method.
var colours = new Dictionary<string, string> {
    { "red", "#ff0000" },
    { "green", "#00ff00" },
    { "blue", "#0000ff" }
};

int[] arrayOfInt = { 1, 2, 3, 4, 5 };

Bir diğeri:

4) Otomatik özellikler farklı kapsamlara sahip olabilir:

public int MyId { get; private set; }

Bana hatırlattığın için teşekkürler @pzycoman:

5) Ad alanı takma adları (bu özel ayırıma ihtiyacınız olması gerekmez):

using web = System.Web.UI.WebControls;
using win = System.Windows.Forms;

web::Control aWebControl = new web::Control();
win::Control aFormControl = new win::Control();

14
# 3'te Enumerable.Range (1,5)
Echostorm

18
bence int [] nums = {1,2,3} ile dizileri başlatabildiğinizi; beri 1.0 :) "yeni" anahtar kelimeye bile gerek yok
Lucas

13
ayrıca parametresiz lambda () => DoSomething ();
Pablo Retyk

5
Her ikisini de kullandım {get; iç küme; } ve Al; korumalı set; }, yani bu model tutarlıdır.
Keith

7
@Kirk Broadhurst - haklısınız - new web.Control()bu örnekte de işe yarar . ::Adlı bir sınıf var bu yüzden sözdizimi kuvvetleri bu bir ad takma ad olarak öneki tedavi etmek webve web::Controlsüre sözdizimi, iş yine olur web.Controlsözdizimi sınıf veya isim alanını kontrol edip bilemeyiz. Bu nedenle her ::zaman ad alanı takma adları yaparken kullanmaya eğilimliyim .
Keith

286

Bir süredir "as" anahtar kelimesini bilmiyordum.

MyClass myObject = (MyClass) obj;

vs

MyClass myObject = obj as MyClass;

İkincisi, bir sınıf cast istisnası atmak yerine obj bir MyClass değilse null değerini döndürür.


42
Yine de aşırı yapma. Birçok kişi, (ToType) x'in anlambilimini isteseler bile sözdizimini tercih ettiği için kullanıyor gibi görünüyor.
Scott Langham

4
Daha iyi performans sunduğuna inanmıyorum. Profil verdiniz mi? (Açıkçası oyuncu kadrosu başarısız olduğunda yapar ... ama (MyClass) oyuncu kadrosu kullandığınızda, başarısızlıklar olağanüstü .. ve son derece nadirdir (eğer olurlarsa), bu yüzden fark etmez.
Scott Langham

7
Bu, yalnızca normal durum kadro başarısız olursa daha performanslıdır. Aksi takdirde, doğrudan yayın (tür) nesnesi daha hızlıdır. Doğrudan oyuncu kadrosunun istisna atması boş değer döndürmekten daha uzun sürer.
Spence

15
"As" anahtar kelimesinin aynı satırları boyunca ... "is" anahtar kelimesi de aynı derecede yararlıdır.
dkpatt

28
Daha önce bir InvalidCastException geçirdiğinizde kötüye kullanabilir ve daha sonra NullReferenceException özel durumunuz olabilir.
Andrei Rînea

262

Sevdiğim iki şey Otomatik özelliklerdir, böylece kodunuzu daha da daraltabilirsiniz:

private string _name;
public string Name
{
    get
    {
        return _name;
    }
    set
    {
        _name = value;
    }
}

olur

public string Name { get; set;}

Ayrıca nesne başlatıcılar:

Employee emp = new Employee();
emp.Name = "John Smith";
emp.StartDate = DateTime.Now();

olur

Employee emp = new Employee {Name="John Smith", StartDate=DateTime.Now()}

6
Otomatik Özellikler'in yalnızca C # 3.0 özelliği olduğu belirtilmelidir mi?
Jared Updike

21
Otomatik Özellikler 3.0 derleyici ile tanıtıldı. Ancak derleyici çıkış 2.0 koduna ayarlanabildiğinden iyi çalışır. Daha eski bir derleyicide 2.0 kodunu otomatik özelliklerle derlemeye çalışmayın!
Joshua Shannon

74
Birçok kişinin fark etmediği bir şey, get ve set'in farklı erişilebilirliğe sahip olabileceğidir, örneğin: public string Name {get; özel set;}
Nader Shirazie

7
Otomatik Özellikler ile ilgili tek sorun, varsayılan başlatma değeri sağlamanın mümkün olmadığıdır.
Stein Åsmul

7
@Aneves: hayır değil. Bu sayfadan: DefaultValueAttribute, üyenin otomatik olarak özniteliğin değeriyle başlatılmasına neden olmaz. Kodunuzda başlangıç ​​değerini ayarlamanız gerekir. [DefaultValue]tasarımcı için kullanılır, bu nedenle bir özelliğin kalın olarak gösterilip gösterilmeyeceğini bilir (varsayılan olmayan).
Roger Lipscombe

255

Genel türlerde 'varsayılan' anahtar kelime:

T t = default(T);

T bir başvuru türüyse 'null', int ise 0, boolean ise false vb. ile sonuçlanır.


4
Artı: yazın? Nullable <type> kısayolu olarak. default (int) == 0, ancak default (int?) == null.
sunside


221

@ Derleyiciye bir dizede kaçış karakterini yoksaymasını söyler.

Sadece bunu açıklığa kavuşturmak istedim ... kaçış karakterlerini görmezden gelmesini söylemez, derleyiciye dizeyi değişmez olarak yorumlamasını söyler.

Eğer varsa

string s = @"cat
             dog
             fish"

aslında şu şekilde yazdırılacaktır (girinti için kullanılan boşlukları bile içerdiğini unutmayın):

cat
             dog
             fish

dize girinti için kullandığınız tüm boşlukları içermez mi?
andy

18
Evet buna kelimesi kelimesine dize denir.
Joan Venge

4
Çıktının yazdırılacak alanları da göstermesi daha açık olurdu. Şu anda yeni satır karakterleri yazdırılmış gibi görünüyor, ancak boşluklar yok sayılıyor.
aleemb

Normal ifadelerden ve uzun SQL sorgularından kaçmak için çok yararlıdır.
ashes999

Ayrıca eşler {{için {ve }}için }için yararlı bir hale string.Format().
Ferruccio

220

C # (.NET 3.5) en az bilinen ve daha az bilinen özelliklerinden biri , özellikle Generics ve Lambdas ile birleştirildiğinde İfade Ağaçları olduğunu düşünüyorum. Bu, NInject ve Moq gibi daha yeni kitaplıkların kullandığı API oluşturmaya yönelik bir yaklaşımdır.

Örneğin, bir yöntemi bir API ile kaydetmek istediğimi ve API'nın yöntem adını alması gerektiğini varsayalım

Bu sınıf verildiğinde:

public class MyClass
{
     public void SomeMethod() { /* Do Something */ }
}

Daha önce, geliştiricilerin bunu dizelerle ve türlerle (veya büyük ölçüde dize tabanlı başka bir şeyle) yaptıklarını görmek çok yaygındı:

RegisterMethod(typeof(MyClass), "SomeMethod");

Güçlü yazma eksikliği yüzünden berbat. "SomeMethod" adını değiştirirsem ne olur? Şimdi, 3.5'te, bunu güçlü bir şekilde yazabilirim:

RegisterMethod<MyClass>(cl => cl.SomeMethod());

RegisterMethod sınıfının şu şekilde kullandığı Expression<Action<T>>:

void RegisterMethod<T>(Expression<Action<T>> action) where T : class
{
    var expression = (action.Body as MethodCallExpression);

    if (expression != null)
    {
        // TODO: Register method
        Console.WriteLine(expression.Method.Name);
    }
}

Şu anda Lambdas ve İfade Ağaçları'na aşık olmamın büyük bir nedeni bu.


3
FieldInfo, PropertyInfo, vb ile aynı şeyi yapan bir yansıma yardımcı programı sınıfı var ...
Olmo

Evet, bu harika. EditValue(someEmployee, e => e.FirstName);İş mantığımda olduğu gibi kod yazmak ve otomatik olarak bir ViewModel ve Görünüm bu özelliği düzenlemek için tüm sıhhi tesisat mantığı oluşturmak için böyle yöntemleri kullanabildi (yani, "Ad" ve bir TextBox ile bir etiket kullanıcı adı düzenlediğinde ve alıcıyı kullanarak Görünümü güncellediğinde, FirstName özelliğinin ayarlayıcısını çağıran bir bağlayıcı). Bu, C #'daki yeni dahili DSL'lerin çoğu için temel gibi görünüyor.
Scott Whitlock

4
Bunların daha az anlaşıldığı kadar az bilinmediğini düşünüyorum.
Justin Morgan

Neden bir yöntem kaydettirmeniz gerekiyor? Bunu daha önce hiç kullanmadım - bu nerede ve ne zaman kullanılır?
MoonKnight

209

aklıma " verim " gelirdi. [DefaultValue ()] gibi bazı özellikler de favorilerim arasında.

" Var " anahtar sözcüğü biraz daha bilinir, ancak .NET 2.0 uygulamalarında da kullanabilirsiniz (.NET 3.5 derleyicisini kullandığınız ve 2.0 koduna ayarladığınız sürece) çok bilinmemektedir. iyi.

Düzenleme: kokos, işaret ettiğiniz için teşekkürler ?? gerçekten yararlı. Bunun için google için biraz zor olduğundan (?? sadece yok sayılır gibi), işte o operatör için MSDN dokümantasyon sayfası: ?? Operatör (C # Referansı)


14
Varsayılan değerin belgeleri, mülkün değerini gerçekten ayarlamadığını söylüyor. Bu sadece görselleştiriciler ve kod üreticileri için bir yardımcıdır.
Boris Callens

2
DefaultValue için: Bu arada, bazı kütüphaneler bunu kullanır. ASP.net MVC bir denetleyici eylem parametreleri (varsayılan null olmayan türler için çok yararlıdır) DefaultValue kullanır. Elbette, bu değer bir derleyici tarafından değil, MVC'nin kodu tarafından ayarlandığından kod üretecidir.
Michael Stum

6
Adı ?? operatörü "Null Coalescing" operatörü
Armstrongest

verim benim favorim, birleşme operatörü de orada. CAS veya montaj imzası, güçlü isimler, GAC hakkında hiçbir şey görmüyorum ... Sanırım sadece CAS C # ... ... ancak pek çok geliştiricinin güvenlik hakkında hiçbir fikri yok.
BrainSlugs83

198

Çoğu C # geliştiricisinin 'nullable' türlerini bilmediğini fark etme eğilimindeyim. Temel olarak, sıfır değerine sahip olabilen ilkeller.

double? num1 = null; 
double num2 = num1 ?? -100;

Bir null çift, Set num1 null, ardından normal bir çift, set NUM2 için, NUM1 veya -100 eğer num1 boş oldu.

http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspx

Nullable türü hakkında bir şey daha:

DateTime? tmp = new DateTime();
tmp = null;
return tmp.ToString();

döndürür String.Empty. Daha fazla ayrıntı için bu bağlantıyı kontrol edin


1
DateTime değeri null olarak ayarlanamaz.
Jason Jackson

2
O zaman "int" sadece C # syntaktik şeker System.Int32 için mi? Nullable türleri etrafında oluşturulmuş derleyici desteği vardır, örneğin null olarak ayarlanmasına olanak tanır (örneğin, yalnızca genel yapılar kullanılarak yapılamaz) ve bunları altta yatan tür olarak bokslar.
P Daddy

4
@P Daddy - evet, int System.Int32 için sözdizimsel şekerdir. Tamamen değiştirilebilir, tıpkı int gibi? === Int32? === Sıfırlanabilir <Int32> ===
Sıfırlanabilir

6
@ cck: Evet, int System.Int32 için bir takma ad olarak T? Nullable <T> için bir takma addır, ancak yalnızca sözdizimsel şeker değildir . Dilin tanımlanmış bir parçası. Takma adlar sadece kodun okunmasını kolaylaştırmakla kalmaz, aynı zamanda modelimize daha iyi uyarlar. Nullable <Double> ifadesini çift olarak mı ifade ediyorsunuz? bu şekilde içerilen değerin yalnızca Double tipinde somutlaştırılan bazı genel yapıların değil, çift olduğu (veya olabileceği) perspektifinin altını çizer. (devam)
P Daddy

3
... Her durumda, argüman takma adlarla ilgili değildi (bu sadece zayıf bir benzetme idi, sanırım), ancak null olabilecek türlerin - tercih ettiğiniz herhangi bir sözdizimini kullanan - gerçekten bir dil özelliği değil, sadece jeneriklerin bir ürünü değil. Nullların tüm işlevlerini (null, operatör iletme, altta yatan tipte boks ya da null, boş null birleştirme ve asoperatörlerle uyumluluk) karşılaştırma / atama sadece jeneriklerle çoğaltamazsınız. Tek başına sıfırlanabilir <T> ilkeldir ve yıldızdan uzaktır, ancak dilin parçası olarak sıfırlanabilir türler kavramı tekme kıçıdır.
P Daddy

193

Belgesiz C # anahtar kelimeleri şeklinde bazı ilginç gizli C # özellikleri:

__makeref

__reftype

__refvalue

__arglist

Bunlar, jeneriklerden önce daha verimli bir boks / kutudan çıkarma için eklenen belgesiz C # anahtar kelimeleridir (hatta Visual Studio bunları tanır!). System.TypedReference yapısı ile koordineli olarak çalışırlar.

Ayrıca değişken uzunluklu parametre listeleri için kullanılan __arglist vardır.

İnsanların pek bilmediği bir şey System.WeakReference - bir nesneyi takip eden ancak çöp toplayıcının onu toplamasına izin veren çok kullanışlı bir sınıftır.

En yararlı "gizli" özellik, getiri anahtar kelimesi olacaktır. Gerçekten gizli değil, ama birçok insan bunu bilmiyor. LINQ bunun üzerine inşa edilmiştir; kaputun altında bir durum makinesi oluşturarak gecikmeli olarak yürütülen sorgulara izin verir. Raymond Chen geçtiğimiz günlerde içten gelen cesur ayrıntılardan bahsetti .


2
Peter Bromberg'in belgelenmemiş anahtar kelimeleri hakkında daha fazla bilgi . Bunları kullanmak için nedenler varsa hala anlamıyorum.
HuBeZa

@HuBeZa, jeneriklerin ortaya çıkışı ile __refType, __makeref ve __refvalue kullanmak için pek çok (herhangi bir?) İyi neden yoktur. Bunlar öncelikle .NET 2'de jeneriklerden önce boks yapmaktan kaçınmak için kullanıldı
Judah Gabriel Himango

Matt, .NET 2'de jeneriklerin tanıtılmasıyla, bu anahtar kelimeleri kullanmak için çok az neden var, çünkü amaçları değer türleriyle uğraşırken boks yapmaktan kaçınmaktı. HuBeZa'nın bağlantısına bakın ve ayrıca bkz. Codeproject.com/Articles/38695/UnCommon-C-keywords-A-Look#ud
Judah Gabriel Himango

185

Saf, güvenli C # içindeki sendikalar (C ++ paylaşılan bellek türü)

Güvenli olmayan moda ve işaretlere başvurmadan, sınıf üyelerinin bir sınıf / yapıdaki bellek alanını paylaşmasını sağlayabilirsiniz. Aşağıdaki sınıf verildiğinde:

[StructLayout(LayoutKind.Explicit)]
public class A
{
    [FieldOffset(0)]
    public byte One;

    [FieldOffset(1)]
    public byte Two;

    [FieldOffset(2)]
    public byte Three;

    [FieldOffset(3)]
    public byte Four;

    [FieldOffset(0)]
    public int Int32;
}

Bayt alanlarının değerlerini Int32 alanını ve tam tersini değiştirerek değiştirebilirsiniz. Örneğin, bu program:

    static void Main(string[] args)
    {
        A a = new A { Int32 = int.MaxValue };

        Console.WriteLine(a.Int32);
        Console.WriteLine("{0:X} {1:X} {2:X} {3:X}", a.One, a.Two, a.Three, a.Four);

        a.Four = 0;
        a.Three = 0;
        Console.WriteLine(a.Int32);
    }

Bunu çıktılar:

2147483647
FF FF FF 7F
65535

sadece System.Runtime.InteropServices kullanarak ekleyin;


7
@George, c sendika bildirimlerini kullanarak soketler üzerinden eski uygulamalarla iletişim kurduğunuzda harikalar yaratır.
scottm

2
Ofset 0'da int ve float demek de anlamlıdır. Kayan nokta sayılarını bazen yapmak istediğiniz bit maskeleri olarak değiştirmek istiyorsanız, ihtiyacınız olan şey budur. Özellikle kayan nokta sayıları hakkında yeni şeyler öğrenmek istiyorsanız.
John Leidegren

2
Bu konuda can sıkıcı bir şey, eğer bunu kullanacaksanız, derleyicinin init işlevindeki TÜM değişkenleri ayarlamaya zorlayacağı bir yapıdır. Eğer varsa: genel A (int int32) {Int32 = int32; } "Arayan kişiye kontrol döndürülmeden önce" Alan 'Bir' tam olarak atanmalıdır "atar, bu nedenle Bir = İki = Üç = Dört = 0; de.
manixrock

2
Bunun, çoğunlukla ikili verilerle kullanımı vardır. Ben 0, 1, 2 ve 3 dört bileşen için int32 @ 0 ve dört bayt ile bir "Piksel" yapı kullanın Görüntü verilerini hızlı ve kolay bir şekilde işlemek için harika.
snarf

57
Uyarı: Bu yaklaşım endianizmi dikkate almaz. Bu, C # kodunuzun tüm makinelerde aynı şekilde çalışmadığı anlamına gelir. Little endian CPU'larda (önce en az önemli baytı saklayan), gösterilen davranış kullanılacaktır. Ancak big-endian CPU'larda, baytlar beklediğinizden ters çevrilecektir. Bunu üretim kodunda nasıl kullandığınıza dikkat edin - kodunuz bazı mobil cihazlar ve diğer donanımlar için taşınabilir olmayabilir ve açık olmayan yollarla bozulabilir (örn. Görünüşte aynı formatta ancak aslında bayt sırası ters çevrilmiş olan iki dosya).
Ray Burns

176

Anahtar kelime olan değişken adları için @ kullanma.

var @object = new object();
var @string = "";
var @if = IpsoFacto(); 

38
Neden bir anahtar kelimeyi değişken adı olarak kullanmak istersiniz? Bana bunun kodun daha az okunabilir ve gizlenmesini sağlayacak gibi geldi.
Jon

41
Bunun nedeni,
CLI'nin

69
Eğer asp.net MVC HTML yardımcılarını kullanmak ve bir HTML sınıfı tanımlamak isterseniz, sınıf anahtar kelimesi olarak tanınmayacak şekilde @class kullanabileceğinizi bilmek sizi mutlu edecektir
Boris Callens

31
Genişletme yöntemleri için harika. kamu statik geçersiz DoSomething (bu Bar @ bu, dize foo) {...}
Jonathan C Dickinson

45
@zihotki: Yanlış. var a = 5; Console.WriteLine (@a); Baskılar 5
SLaks

168

Sonunda herhangi bir blok veya sonlandırıcı çağırmadan programınızdan çıkmak istiyorsanız FailFast kullanın :

Environment.FailFast()

12
Bu yöntemin ayrıca bir bellek dökümü oluşturduğunu ve Windows hata günlüğüne bir ileti yazdığını unutmayın.
RickNZ

1
Bu yöntem kullanıldığında hiçbir kesinleştirici veya uygulama etki alanı kaldırma olayı çağrılmayacaktır ...
AwkwardCoder

1
İpucu için +1, ama bu C # değil, .NET BCL.
Abel

System.Diagnostics.Process.GetCurrentProcess (). Kill () daha hızlı
Tolgahan Albayrak

153

Bir yöntemden anonim türler döndürme ve yansıma olmadan üyelere erişme.

// Useful? probably not.
private void foo()
{
    var user = AnonCast(GetUserTuple(), new { Name = default(string), Badges = default(int) });
    Console.WriteLine("Name: {0} Badges: {1}", user.Name, user.Badges);
}

object GetUserTuple()
{
    return new { Name = "dp", Badges = 5 };
}    

// Using the magic of Type Inference...
static T AnonCast<T>(object obj, T t)
{
   return (T) obj;
}

42
Bu sana hiçbir şey getirmiyor. Aslında tehlikelidir. GetUserTuple, birden çok tür döndürecek şekilde değiştirilirse ne olur? Yayın çalışma zamanında başarısız olur. C # / Net ile ilgili en güzel şeylerden biri derleme zamanı kontrolüdür. Yeni bir tür oluşturmak çok daha iyi olur.
Jason Jackson

9
@Jason muhtemelen yararlı olmadığını söylemiştim ama şaşırtıcı (ve gizli olduğunu düşündüm).
denis phillips

31
Havalı olsa da, bu oldukça zayıf bir tasarım seçeneği gibi görünüyor. Anonim türü temel olarak iki yerde tanımladınız. Bu noktada, gerçek bir yapı beyan edin ve doğrudan kullanın.
Paul Alexander

6
@George: Böyle bir sözleşmeye ... yapı denir mi?
R. Martinho Fernandes

2
bu hile 'sample by cast' olarak adlandırılır ve anonim tür döndüren yöntem başka bir montajda bulunuyorsa çalışmaz.
desco

146

Normal ifadeler ve dosya yolları için kullanışlı bir yöntem:

"c:\\program files\\oldway"
@"c:\program file\newway"

@ Derleyiciye bir dizede kaçış karakterini yoksaymasını söyler.


27
Ayrıca, @ sabiti içeride yeni satırları kabul eder. Bir dizeye çok satırlı bir komut dosyası atarken mükemmeldir.
Tor Haugen

11
Başka bir deyişle, tırnak işaretinden kaçmayı da unutmayın. [kod] var candy = @ "Ben" "kırmızı" "şekerler seviyorum."; [/ kod]
Dave

5
Path.Combine ile yollar oluşturma eğilimindeyim. Kesinlikle @ regex için kullanın!
Dan McClain

6
@new ayrıca bir anahtar kelime yerine bir değişkendir: @this, @int, @return, @interface ... vb :)
IAbstract 28:10

Bu yakın bir yere gelmiyor: Ama C # hayranlarının, bağımlılarının, uzmanların bile zar zor bildiği en gizli özellikler veya C # numaraları nelerdir?
publicgk

141

Katmalar. Temel olarak, birkaç sınıfa bir özellik eklemek istiyorsanız, ancak hepsi için bir temel sınıf kullanamıyorsanız, her sınıfı bir arabirim (üyesiz) uygulamak için alın. Daha sonra, bir uzantısı yöntem bilgileri arabirimi için , yani,

public static DeepCopy(this IPrototype p) { ... }

Tabii ki, bir miktar netlik feda edilir. Ama işe yarıyor!


4
Evet, bu uzatma yöntemlerinin gerçek gücü olduğunu düşünüyorum. Temel olarak arayüz yöntemlerinin uygulanmasına izin verirler.
John Bubriski

NHibernate (veya Castle ActiveRecord) kullanıyorsanız ve koleksiyonlarınız için arayüzler kullanmanız gerektiğinde de kullanışlıdır. Bu şekilde toplama arabirimlerine davranış verebilirsiniz.
Ryan Lundy

Kayıt için tüm LINQ yöntemlerinin uygulanması bu şekildedir.
WCWedin

NHibernate veya Castle ActiveRecord'daki toplama arayüzleri ile uzatma yöntemlerini kullanarak yukarıda bahsettiğim şey hakkında konuşan bir link: devlicio.us/blogs/billy_mccafferty/archive/2008/09/03/…
Ryan Lundy

7
Sadece uzantısı özelliklerine izin verdiyse !!!! Salt okunur bir özellik olmak için yalvaran bir uzantı yöntemi yazmaktan nefret ettim ....
John Gibb

130

Neden hiç kimse Nullable <bool> kullanmak isteyeyim emin değilim. :-)

Doğru, Yanlış, FileNotFound ?


87
bir kullanıcının evet sorusuna cevap vermesini beklemezseniz, soru cevaplanmadıysa null uygun olur
Omar Kooheji

22
Sıfırlanabilir türler, tablo sütunlarının genellikle geçersiz olduğu bir veritabanıyla etkileşim için kullanışlıdır.
tuinstoel

11
Evet, Hayır, Maybee?
Dan Blair

21
ThreeState CheckBox
Shimmy Weitzhandler'ın

8
SQL'de olduğu gibi: Evet / hayır / bilinmiyor.
erikkallen

116

Bu, isimlendirildiği kadar "gizli" değildir.

"Harita", "azalt" ve "filtre" algoritmalarına çok dikkat edilir. Çoğu insanın fark etmediği şey, .NET 3.5'in bu algoritmaların üçünü de eklemesidir, ancak LINQ'nun bir parçası olmalarına dayanarak onlara çok SQL ish isimleri verdi.

"map" => Seç
Verileri bir formdan diğerine dönüştürür

"reduce" => Toplam
Toplama Değerleri tek bir sonuçta toplar

"filter" => Nerede
Verileri ölçütlere göre filtreler

LINQ'yu yineleme ve koşullu olarak kullanılan koleksiyonlar üzerinde satır içi çalışma yapmak için kullanma becerisi inanılmaz derecede değerli olabilir. Tüm LINQ genişletme yöntemlerinin kodunuzu çok daha kompakt ve bakımı kolay hale getirmeye nasıl yardımcı olabileceğini öğrenmeye değer.


1
Select ayrıca monad'larda "dönüş" işlevi gibi davranır. Bkz. Stackoverflow.com/questions/9033/hidden-features-of-c#405088
Mark Cidade

1
"Select" kullanmak yalnızca SQLish sözdizimini kullanıyorsanız gereklidir. Uzantı yöntemi sözdizimini kullanırsanız - someCollection.Where (item => item.Price> 5,99M) - select deyimlerinin kullanılması gerekmez.
Brad Wilson

7
@Brad, bu (nerede) bir filtre işlemidir.
Seçmeden

2
LINQ, bence C #'a gelen en büyük şey: stackoverflow.com/questions/2398818/…
Leniel Maccaferri

1
Aggregate'in en küçük imzası "azaltma" işlevidir, Aggregate'in orta imzası çok daha güçlü "katlama" işlevidir!
Brett Widmeier

115
Environment.NewLine

sistemden bağımsız yeni satırlar için.


10
Bu konuda can sıkıcı olan şey, kompakt çerçeveye dahil edilmemesidir.
Stormenet

14
Bunun uygulamanın ana bilgisayar platformuna özgü olduğunu belirtmeye değer - bu nedenle başka bir sistem için tasarlanan veriler oluşturuyorsanız, \ n veya \ r \ n'yi uygun şekilde kullanmalısınız.
Mesh

Bu, C # 'nin bir özelliği değil, .NET BCL'nin bir parçasıdır.
Abel

111

Bir String.Format ifadesinin içinde süslü parantez kullanmaya çalışıyorsanız ...

int foo = 3;
string bar = "blind mice";
String.Format("{{I am in brackets!}} {0} {1}", foo, bar);
//Outputs "{I am in brackets!} 3 blind mice"

19
@Kyralessa: Aslında, evet, bunlar diş telleri, ancak "kıvırcık parantezler" onlar için alternatif bir isim. [ve ]köşeli parantezler, ve <ve >köşeli parantezler bulunmaktadır. Bkz. En.wikipedia.org/wiki/Bracket .
Mart'ta icktoofay

4
Haklısın. Ama yorum yaptığımda, "kıvırcık" parantez demedi.
Ryan Lundy

2
Çok güzel bir işaret. İlk String.Format'ım şöyle görünüyordu: String.Format ("{0} Kıvrımlı parantezler içindeyim {1} {2} {3}", "{", "}", 3, "kör fareler"); Bunlardan kaçmanın {{ve}} kullanılarak yapıldığını öğrendikten sonra çok mutlu oldum :)
Gertjan

Muahahahaa ... Zaten 3 yıldır programlama Net ve ben bunu bilmiyordum. : D
Arnis Lapsa

kaçış dizilerine benzer şekilde hareket eden "kıvırcık" parantez ??
Pratik

104
  1. ??- birleştirme operatörü
  2. using ( deyim / yönerge ) - Dispose'i çağırmaktan daha fazlası için kullanılabilecek harika anahtar kelime
  3. salt okunur - daha fazla kullanılmalıdır
  4. netmodules - çok kötü Visual Studio'da destek yok

6
using, uzun bir ad alanını daha uygun bir dizeyle diğer ad olarak adlandırmak için de kullanılabilir; örneğin: using ZipEncode = MyCompany.UtilityCode.Compression.Zip.Encoding; Burada daha fazlası var: msdn.microsoft.com/en-us/library/sf0df423.aspx
Dave R.

2
Gerçekten aynı şey değil. Dispose çağrılırken, using yönergesini kullandığınız türleri takma yaparken, using deyimini kullanabilirsiniz.
Øyvind Skaar

2
Her ne kadar # 1 adında bir isim istiyorsanız (üçlü operatörle yaptığınız gibi) ?? null birleştirme operatörü olarak adlandırılır.
J. Steen

4
@ LucasAardvark: J Steen'in de belirttiği gibi buna boş birleştirici operatör denir. Arayın!
kokos

1
Aramak için ?? google try şirketinde operator: google.com/search?q=c%23+%3F%3F+operator
backslash17

103

@Ed, nitpicking'dan biraz daha fazlası olduğu için bunu yayınlamak konusunda biraz duraksamıyorum. Ancak, ben kod örnekte işaret:

MyClass c;
  if (obj is MyClass)
    c = obj as MyClass

'İs' kullanacaksanız, neden 'as' kullanarak güvenli bir oyuncu ile takip edesiniz? Nesnenin gerçekten de MyClass olduğunu tespit ettiyseniz, bataklık standardı bir oyuncu kadrosu:

c = (MyClass)obj

... asla başarısız olmayacak.

Benzer şekilde, sadece şunu söyleyebilirsiniz:

MyClass c = obj as MyClass;
if(c != null)
{
   ...
}

Emin olmak için .NET'in innards hakkında yeterli bilmiyorum, ama içgüdülerim bana bunun en fazla iki tip döküm işlemini en fazla bire indireceğini söylüyor. İşleme bankasını her iki şekilde de kırmak pek olası değildir; şahsen, ikinci formun da daha temiz göründüğünü düşünüyorum.


16
Oyuncular tam türdeyse (nesne "A" ise, ondan türetilmediğinde "A" ya çevrilir), düz döküm "as" dan ~ 3x DAHA HIZLI olur. Türetilmiş bir tür dökülürken (nesne "A" dan türeyen "B" olduğunda "A" ya çevrilir), düz döküm "as" değerinden ~ 0.1x daha yavaştır. "is", o zaman "as" sadece aptalca.
P Daddy

2
Hayır, ancak "if ((c = obj olarak MyClass)! = Null)" yazabilirsiniz.
Dave Van den Eynde

10
isve askullanıcı yayınları yapmaz. Bu nedenle, yukarıdaki kod isoperatöre obj'ün MyClass'tan türetilmiş olup olmadığını soruyor (veya örtük bir sistem tanımlı dökümüne sahip). Ayrıca, isbaşarısız null. Bu uç durumların her ikisi de kodunuz için önemli olabilir. Örneğin, şunu yazmak isteyebilirsiniz: if( obj == null || obj is MyClass ) c = (MyClass)obj; Ancak bu kesinlikle aşağıdakilerden farklıdır: try { c = (MyClass)obj; } catch { }çünkü birincisi kullanıcı tanımlı dönüşüm gerçekleştirmez, ancak ikincisi yapar. Olmadan nullçek, eski de belirlememesini czaman objolduğu null.
Adam Luter

2
IL'de oyuncu kadrosu bir CASTCLASS'a gider, ancak as / ISINST komutuna gider.
John Gibb

5
Ben döküm, bunun için bir test koştum IEnumerable<int>için List<int>, ve döküm object( new object()kadar) IEnumerable<int>doğrudan dökme: Emin yanlışlık olmadığından emin olmak için, döküm olarak 6.75ns,: 5.69ns 5.43ns, IS-> dökme olarak. Ardından geçersiz yayınları test etme: doğrudan yayın: 3125000ns, yayınlandığı gibi: 5.41ns. Sonuç:% 1 faktörü hakkında endişelenmeyi bırakın ve kullandığınızdan emin olun. Son bölümün, geri kalanının önemli olmadığını unutmayın (.Net FW 4.0, sürüm oluşturma)
Aidiakapi

98

Belki ileri bir teknik değil, ama her zaman gördüğüm bir şey beni deli ediyor:

if (x == 1)
{
   x = 2;
}
else
{
   x = 3;
}

yoğunlaştırılabilir:

x = (x==1) ? 2 : 3;

10
Üçlü operatör grubumda yasaklandı. Bazı insanlar bundan hoşlanmıyor ama nedenini hiç anlamadım.
Justin

13
Sanırım çünkü bunlar aynı şeyler değil, operatör değil, bir açıklama. İlk yaklaşımı kendim tercih ederim. Daha tutarlı ve kolayca genişletilebilir. İşleçler ifadeler içeremez, bu nedenle gövdeyi genişletmeniz gerektiğinde, bu üçlü operatörü bir if ifadesine dönüştürmeniz gerekir
kervin

16
x ++ 'a yoğunlaştırılabilir; Tamam anlamsız ^^
François

5
@Guillaume: x: x = 2 + System.Math.Min (1, System.Math.Abs ​​(x-1)) 'nin tüm değerlerini hesaba katmak;
mbeckish

38
Aslında "koşullu operatör" denir - öyle bir üç argüman alır çünkü üçlü operatörü. en.wikipedia.org/wiki/Conditional_operator
Blorgbeard
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.