Fitur Tersembunyi C #? [Tutup]

1475

Ini muncul di benak saya setelah saya mempelajari yang berikut dari pertanyaan ini :

where T : struct

Kami, pengembang C #, semua tahu dasar-dasar C #. Maksud saya deklarasi, kondisional, loop, operator, dll.

Beberapa dari kita bahkan menguasai hal-hal seperti Generik , tipe anonim , lambdas , LINQ , ...

Tapi apa saja fitur atau trik paling tersembunyi dari C # yang bahkan tidak diketahui oleh penggemar, pecandu, dan pakar C #?

Berikut adalah fitur yang terungkap sejauh ini:


Kata kunci

Atribut

Sintaksis

Fitur Bahasa

Fitur Visual Studio

Kerangka

Metode dan Properti

Tips dan Trik

  • Metode yang bagus untuk penangan acara oleh Andreas HR Nilsson
  • Perbandingan huruf besar oleh John
  • Akses tipe anonim tanpa refleksi oleh dp
  • Cara cepat untuk instantiate properti koleksi dengan malas oleh Will
  • JavaScript-seperti fungsi inline anonim oleh roosteronacid

Lain

Serhat Ozgel
sumber

Jawaban:

752

Ini bukan C # per se, tapi saya belum melihat siapa pun yang benar-benar menggunakan System.IO.Path.Combine()sejauh yang seharusnya. Faktanya, seluruh kelas Path benar-benar bermanfaat, tetapi tidak ada yang menggunakannya!

Saya berani bertaruh bahwa setiap aplikasi produksi memiliki kode berikut, meskipun seharusnya tidak:

string path = dir + "\\" + fileName;
ageektrapped
sumber
584

lambdas dan inferensi tipe diremehkan. Lambdas dapat memiliki banyak pernyataan dan merangkap sebagai objek delegasi yang kompatibel secara otomatis (pastikan pencocokan tanda tangan) seperti pada:

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

Perhatikan bahwa saya tidak memiliki new CancellationEventHandlerdan tidak harus menentukan jenis senderdan e, mereka dapat disimpulkan dari acara tersebut. Itulah sebabnya ini kurang merepotkan untuk menulis keseluruhan delegate (blah blah)yang juga mengharuskan Anda untuk menentukan jenis parameter.

Lambdas tidak perlu mengembalikan apa pun dan mengetik inferensi sangat kuat dalam konteks seperti ini.

Dan BTW, Anda selalu dapat mengembalikan Lambdas yang membuat Lambdas dalam pengertian pemrograman fungsional. Misalnya, inilah lambda yang membuat lambda yang menangani acara Button.Klik:

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);

Perhatikan chaining: (dx, dy) => (sender, e) =>

Nah, itu sebabnya saya senang telah mengambil kelas pemrograman fungsional :-)

Selain petunjuk dalam C, saya pikir itu hal mendasar lain yang harus Anda pelajari :-)

chakrit
sumber
528

Dari Rick Strahl :

Anda dapat rantai ?? operator sehingga Anda dapat melakukan banyak perbandingan nol.

string result = value1 ?? value2 ?? value3 ?? String.Empty;
jfs
sumber
454

Obat generik:

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

Hal ini memungkinkan Anda untuk menggunakan ASimpleName, bukanDictionary<string, Dictionary<string, List<string>>> .

Gunakan ketika Anda akan menggunakan hal kompleks panjang besar generik yang sama di banyak tempat.

BlackTigerX
sumber
438

Dari CLR via C # :

Ketika menormalkan string, sangat disarankan agar Anda menggunakan ToUpperInvariant daripada ToLowerInvariant karena Microsoft telah mengoptimalkan kode untuk melakukan perbandingan huruf besar .

Saya ingat suatu kali rekan kerja saya selalu mengubah string menjadi huruf besar sebelum membandingkan. Saya selalu bertanya-tanya mengapa dia melakukan itu karena saya merasa lebih "alami" untuk beralih ke huruf kecil terlebih dahulu. Setelah membaca buku itu sekarang saya tahu mengapa.

jfs
sumber
254
Ketika Anda "mengubah string menjadi huruf besar" Anda membuat objek string sementara kedua. Saya berpikir bahwa perbandingan semacam ini tidak disukai, bahwa cara terbaik adalah: String.Equals (stringA, stringB, StringComparison.CurrentCultureIgnoreCase) yang tidak membuat string ini sama sekali.
Anthony
32
Apa jenis optimasi yang dapat Anda lakukan untuk membandingkan string huruf besar yang tidak dapat dilakukan pada string huruf kecil? Saya tidak mengerti mengapa yang satu lebih optimal dari yang lain.
Parappa
36
Mengubah ke huruf besar daripada huruf kecil juga dapat mencegah perilaku yang salah dalam budaya tertentu. Misalnya, dalam bahasa Turki, dua huruf kecil peta saya ke huruf besar yang sama I. Google "turki i" untuk lebih jelasnya.
Neil
34
Saya mencoba melakukan tolok ukur ToUpperInvariant vs ToLowerInvariant. Saya tidak dapat menemukan perbedaan dalam kinerja mereka di .NET 2.0 atau 3.5. Tentu saja tidak ada yang menjamin "sangat merekomendasikan" menggunakan salah satu dari yang lain.
Rasmus Faber
19
ToUpperInvariant lebih disukai karena membuat semua karakter pulang pergi. Lihat msdn.microsoft.com/en-us/library/bb386042.aspx . Untuk perbandingan, tulis"a".Equals("A", StringComparison.OrdinalIgnoreCase)
SLaks
408

Trik favorit saya adalah menggunakan operator penggabungan nol dan tanda kurung untuk secara otomatis instantiate koleksi untuk saya.

private IList<Foo> _foo;

public IList<Foo> ListOfFoo 
    { get { return _foo ?? (_foo = new List<Foo>()); } }
Akan
sumber
23
Tidakkah Anda merasa sulit untuk membaca?
Riri
72
Agak sulit dibaca untuk noo ... eh, tidak berpengalaman. Tapi ini kompak dan berisi beberapa pola dan fitur bahasa yang harus diketahui dan dipahami oleh programmer. Jadi, meskipun sulit pada awalnya, itu memberikan manfaat menjadi alasan untuk belajar.
38
Instansiasi malas agak malpraktek karena itu adalah pilihan pria yang buruk untuk menghindari memikirkan invarian kelas. Ini juga memiliki masalah konkurensi.
John Leidegren
17
Saya selalu diberitahu bahwa ini adalah praktik buruk, bahwa menelepon properti tidak boleh melakukan sesuatu seperti itu. Jika Anda memiliki satu set di sana dan mengatur nilai ke nol, itu akan sangat aneh bagi seseorang yang menggunakan API Anda.
Ian
8
@ Joel kecuali bahwa pengaturan ListOfFoo ke null bukan bagian dari kontrak kelas juga bukan praktik yang baik. Itu sebabnya tidak ada setter. Itu juga mengapa ListOfFoo dijamin untuk mengembalikan koleksi dan tidak pernah nol. Ini hanya keluhan yang sangat aneh bahwa jika Anda melakukan dua hal buruk (membuat setter dan mengatur koleksi menjadi nol) ini akan mengakibatkan harapan Anda salah. Saya tidak akan menyarankan melakukan Environment.Exit () di pengambil, baik. Tetapi itu juga tidak ada hubungannya dengan jawaban ini.
315

Hindari memeriksa penangan acara nol

Menambahkan delegasi kosong ke acara di deklarasi, menekan kebutuhan untuk selalu memeriksa acara untuk nol sebelum memanggilnya keren. Contoh:

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

Biarkan kamu melakukan ini

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

Alih-alih ini

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

Silakan juga lihat diskusi terkait ini dan posting blog ini oleh Eric Lippert tentang topik ini (dan kemungkinan kerugian).

nol
sumber
87
Saya percaya masalah akan muncul jika Anda mengandalkan teknik ini dan kemudian Anda harus membuat cerita bersambung kelas. Anda akan menghilangkan acara tersebut, dan kemudian pada deserialisasi Anda akan mendapatkan NullRefference .... Jadi orang hanya dapat tetap berpegang pada "cara lama" dalam melakukan sesuatu. Lebih aman.
sirrocco
16
Anda masih dapat mengatur event handler Anda ke nol, sehingga Anda masih bisa mendapatkan referensi nol, dan Anda masih memiliki kondisi balapan.
Robert Paulson
64
Tes profil cepat menunjukkan bahwa event handler yang berlangganan dummy tanpa tes nol membutuhkan kira-kira 2x kali event handler yang tidak berlangganan dengan tes nol. Event handler multicast tanpa tes nol membutuhkan waktu 3,5x waktu singlecast event handler dengan tes nol.
P Ayah
54
Ini menghindari perlunya pemeriksaan nol dengan selalu memiliki pelanggan sendiri. Bahkan sebagai acara kosong ini membawa overhead yang tidak Anda inginkan. Jika tidak ada pelanggan yang Anda tidak ingin memecat acara sama sekali, tidak selalu memecat acara boneka kosong terlebih dahulu. Saya akan mempertimbangkan kode buruk ini.
Keith
56
Ini adalah saran yang mengerikan, karena alasan dalam komentar di atas. Jika Anda harus membuat kode Anda terlihat "bersih", gunakan metode ekstensi untuk memeriksa nol lalu panggil acara tersebut. Seseorang dengan hak istimewa modifikasi harus menambahkan kontra pada jawaban ini.
Greg
305

Yang lainnya, plus

1) generik implisit (mengapa hanya pada metode dan bukan pada kelas?)

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

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

2) lambda sederhana dengan satu parameter:

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

3) jenis dan inisialisasi anonim:

//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 };

Yang lainnya:

4) Properti otomatis dapat memiliki cakupan yang berbeda:

public int MyId { get; private set; }

Terima kasih @pcomcoman untuk mengingatkan saya:

5) Alias ​​Namespace (bukan berarti Anda membutuhkan perbedaan khusus ini):

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

web::Control aWebControl = new web::Control();
win::Control aFormControl = new win::Control();
Keith
sumber
14
di # 3 Anda dapat melakukan Enumerable.Range (1,5)
Echostorm
18
saya pikir Anda dapat menginisialisasi array dengan int [] nums = {1,2,3}; sejak 1.0 :) bahkan tidak memerlukan kata kunci "baru"
Lucas
13
juga lambda tanpa parameter () => DoSomething ();
Pablo Retyk
5
Saya sudah menggunakan keduanya {get; set internal; } dan {get; set yang dilindungi; }, jadi pola ini konsisten.
Keith
7
@Kirk Broadhurst - Anda benar - new web.Control()juga akan berfungsi dalam contoh ini. The ::kekuatan sintaks untuk mengobati awalan sebagai alias namespace, sehingga Anda bisa memiliki kelas yang disebut webdan web::Controlsintaks masih akan bekerja, sedangkan web.Controlsintaks tidak akan tahu apakah untuk memeriksa kelas atau namespace. Karena itu saya cenderung selalu menggunakan ::alias namespace saat melakukan.
Keith
286

Saya tidak tahu kata kunci "sebagai" selama beberapa waktu.

MyClass myObject = (MyClass) obj;

vs.

MyClass myObject = obj as MyClass;

Yang kedua akan mengembalikan nol jika obj bukan MyClass, daripada melemparkan pengecualian pemain kelas.

Mike Stone
sumber
42
Jangan terlalu-melakukannya. Banyak orang tampaknya menggunakannya karena mereka lebih menyukai sintaks walaupun mereka menginginkan semantik dari (ToType) x.
Scott Langham
4
Saya tidak percaya ini menawarkan kinerja yang lebih baik. Sudahkah Anda membuat profil? (Jelas meskipun itu terjadi ketika para pemain gagal ... tetapi ketika Anda menggunakan pemain (MyClass), kegagalan itu luar biasa .. dan sangat jarang (jika mereka terjadi sama sekali), jadi tidak ada bedanya.
Scott Langham
7
Ini hanya lebih berkinerja jika kasus yang biasa adalah para pemain gagal. Kalau tidak, objek cor langsung (tipe) lebih cepat. Dibutuhkan lebih lama untuk pemain langsung untuk melemparkan pengecualian daripada mengembalikan nol.
Spence
15
Tepat di sepanjang baris yang sama dari kata kunci "sebagai" ... kata kunci "adalah" sama bermanfaatnya.
dkpatt
28
Anda dapat menyalahgunakannya dan memiliki NullReferenceException di kemudian hari ketika Anda bisa memiliki InvalidCastException sebelumnya.
Andrei Rînea
262

Dua hal yang saya sukai adalah properti Otomatis sehingga Anda dapat menciutkan kode Anda lebih jauh:

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

menjadi

public string Name { get; set;}

Juga inisialisasi objek:

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

menjadi

Employee emp = new Employee {Name="John Smith", StartDate=DateTime.Now()}
lomaxx
sumber
6
Haruskah dicatat bahwa Properti Otomatis adalah fitur C # 3.0 saja?
Jared Updike
21
Properti Otomatis diperkenalkan dengan kompiler 3.0. Tetapi karena kompiler dapat diatur ke kode keluaran 2.0, mereka bekerja dengan baik. Hanya saja, jangan mencoba mengkompilasi kode 2.0 dengan properti otomatis di kompiler yang lebih lama!
Joshua Shannon
74
Sesuatu yang banyak orang tidak sadari adalah bahwa get and set dapat memiliki aksesibilitas yang berbeda, misalnya: public string Name {get; set pribadi;}
Nader Shirazie
7
Satu-satunya masalah dengan Properti Otomatis adalah tampaknya tidak mungkin untuk memberikan nilai inisialisasi default.
Stein Åsmul
7
@ ANeves: bukan. Dari halaman itu: DefaultValueAttribute tidak akan menyebabkan anggota diinisialisasi secara otomatis dengan nilai atribut. Anda harus menetapkan nilai awal dalam kode Anda. [DefaultValue]digunakan untuk perancang sehingga ia tahu apakah akan menunjukkan properti dalam huruf tebal (artinya tidak default).
Roger Lipscombe
255

Kata kunci 'default' dalam tipe umum:

T t = default(T);

menghasilkan 'null' jika T adalah tipe referensi, dan 0 jika itu adalah int, false jika itu adalah boolean, dan sebagainya.

Eric Minkes
sumber
4
Plus: jenis? sebagai pintasan untuk Nullable <type>. default (int) == 0, tetapi default (int?) == null.
Berjemur
221

@ Memberitahu kompiler untuk mengabaikan karakter escape dalam sebuah string.

Hanya ingin memperjelas yang ini ... itu tidak memberitahu untuk mengabaikan karakter pelarian, itu sebenarnya memberitahu kompiler untuk menafsirkan string sebagai literal.

Jika Anda memiliki

string s = @"cat
             dog
             fish"

itu benar-benar akan dicetak sebagai (perhatikan bahwa itu bahkan termasuk spasi putih yang digunakan untuk indentasi):

cat
             dog
             fish
lomaxx
sumber
bukankah string menyertakan semua spasi yang Anda gunakan untuk indentasi?
andy
18
Ya itu disebut string kata demi kata.
Joan Venge
4
Akan lebih jelas jika output menunjukkan ruang yang akan dicetak juga. Saat ini tampaknya seolah-olah karakter garis baru dicetak tetapi spasi diabaikan.
aleemb
Sangat berguna untuk keluar dari ekspresi reguler dan permintaan SQL yang panjang.
ashes999
Hal ini juga memetakan {{untuk {dan }}untuk }membuatnya berguna untuk string.Format().
Ferruccio
220

Saya pikir salah satu fitur yang paling kurang dihargai dan kurang dikenal dari C # (.NET 3.5) adalah Pohon Ekspresi , terutama ketika dikombinasikan dengan Generics dan Lambdas. Ini adalah pendekatan untuk pembuatan API yang menggunakan perpustakaan baru seperti NInject dan Moq.

Misalnya, katakanlah saya ingin mendaftarkan metode dengan API dan API perlu mendapatkan nama metode

Diberikan kelas ini:

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

Sebelumnya, sangat umum untuk melihat pengembang melakukan ini dengan string dan tipe (atau sesuatu yang sebagian besar berbasis string):

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

Yah, itu menyebalkan karena kurangnya mengetik yang kuat. Bagaimana jika saya mengganti nama "SomeMethod"? Sekarang, dalam 3,5 namun, saya bisa melakukan ini dengan cara yang sangat diketik:

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

Di mana kelas RegisterMethod menggunakan Expression<Action<T>>seperti ini:

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);
    }
}

Ini adalah salah satu alasan utama mengapa saya jatuh cinta dengan Lambdas dan Pohon Ekspresi saat ini.

Jason Olson
sumber
3
Saya memiliki kelas utilitas refleksi yang melakukan hal yang sama dengan FieldInfo, PropertyInfo, dll ...
Olmo
Ya, ini bagus. Saya dapat menggunakan metode seperti ini untuk menulis kode seperti EditValue(someEmployee, e => e.FirstName);dalam logika bisnis saya dan memilikinya secara otomatis menghasilkan semua logika pipa ledeng untuk ViewModel dan Lihat untuk mengedit properti itu (jadi, label dengan teks "Nama Depan" dan Kotak Teks dengan mengikat yang memanggil setter dari properti FirstName ketika pengguna mengedit nama, dan memperbarui tampilan menggunakan pengambil). Ini tampaknya menjadi dasar bagi sebagian besar DSL internal baru di C #.
Scott Whitlock
4
Saya pikir ini tidak begitu dikenal sebagai kurang dipahami.
Justin Morgan
Mengapa Anda perlu mendaftarkan metode? Saya belum pernah menggunakan ini sebelumnya - di mana dan kapan ini akan digunakan?
MoonKnight
209

" Hasil " akan muncul di pikiranku. Beberapa atribut seperti [DefaultValue ()] juga di antara favorit saya.

Kata kunci " var " sedikit lebih dikenal, tetapi Anda juga dapat menggunakannya dalam aplikasi .NET 2.0 (selama Anda menggunakan kompiler .NET 3.5 dan mengaturnya untuk mengeluarkan kode 2.0) tampaknya tidak terlalu dikenal. baik.

Sunting: kokos, terima kasih telah menunjukkan ?? Operator, itu memang sangat berguna. Karena agak sulit untuk google untuk itu (seperti ?? diabaikan), berikut adalah halaman dokumentasi MSDN untuk operator itu: ?? Operator (Referensi C #)

Michael Stum
sumber
14
Dokumentasi nilai default mengatakan itu tidak benar-benar menetapkan nilai properti. Itu hanya pembantu untuk visualiser dan pembuat kode.
Boris Callens
2
Adapun DefaultValue: Sementara itu, beberapa perpustakaan menggunakannya. ASP.net MVC menggunakan DefaultValue pada Parameter Aksi Kontroler (Yang sangat berguna untuk tipe yang tidak dapat dibatalkan). Sebenarnya, ini adalah generator kode karena nilainya tidak ditentukan oleh kompiler tetapi oleh kode MVC.
Michael Stum
6
Nama untuk ?? operator adalah operator "Null Coalescing"
Armstrongest
hasil adalah favorit saya, operator penggabungan ada di sana. Saya tidak melihat apa-apa tentang CAS, atau penandatanganan perakitan, nama-nama kuat, GAC ... Saya kira hanya CAS yang C # ... tetapi begitu banyak pengembang tidak memiliki petunjuk tentang keamanan.
BrainSlugs83
198

Saya cenderung menemukan bahwa sebagian besar pengembang C # tidak tahu tentang tipe 'nullable'. Pada dasarnya, primitif yang dapat memiliki nilai nol.

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

Setel angka nol , num1 , menjadi nol, lalu setel angka ganda, num2 , menjadi num1 atau -100 jika num1 bernilai nol.

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

satu hal lagi tentang tipe Nullable:

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

itu mengembalikan String.Empty. Periksa tautan ini untuk detail lebih lanjut

Brad Barker
sumber
1
DateTime tidak dapat diatur ke nol.
Jason Jackson
2
Jadi apakah "int" hanya gula sintaksis C # untuk System.Int32? Sebenarnya ada dukungan kompiler yang dibangun di sekitar tipe Nullable, memungkinkan pengaturannya menjadi nol, misalnya (yang tidak dapat dilakukan dengan menggunakan generic structs saja), dan meninju mereka sebagai tipe yang mendasarinya.
P Ayah
4
@ P Ayah - ya, int adalah gula sintaksis untuk System.Int32. Mereka benar-benar dipertukarkan, seperti int? === Int32? === Nullable <Int32> === Nullable <int>
cjk
6
@ck: Ya, int adalah alias untuk System.Int32, seperti T? adalah alias untuk Nullable <T>, tetapi itu bukan hanya gula sintaksis. Ini adalah bagian dari bahasa yang didefinisikan. Alias ​​tidak hanya membuat kode lebih mudah dibaca, tetapi juga lebih sesuai dengan model kami. Mengekspresikan Nullable <Double> sebagai ganda? menggarisbawahi perspektif bahwa nilai yang terkandung adalah (atau mungkin) ganda, bukan hanya beberapa struktur generik yang dipakai pada tipe Double. (lanjutan)
P Daddy
3
... Bagaimanapun juga, argumennya bukan tentang alias (itu hanya analogi yang buruk, saya kira), tetapi tipe nullable — menggunakan sintaksis apa pun yang Anda suka — memang fitur bahasa, bukan hanya produk generik. Anda tidak dapat mereproduksi semua fungsi nullables (perbandingan dengan / penugasan null, penerusan operator, tinju dari tipe yang mendasari atau nol, kompatibilitas dengan null penggabungan dan asoperator) dengan obat generik saja. Nullable <T> sendiri adalah rudimenter dan jauh dari bintang, tetapi konsep tipe nullable sebagai bagian dari bahasa adalah kick ass.
P Daddy
193

Berikut adalah beberapa fitur C # tersembunyi yang menarik, dalam bentuk kata kunci C # tidak berdokumen:

__makeref

__reftype

__refvalue

__arglist

Ini adalah kata kunci C # tidak berdokumen (bahkan Visual Studio mengenalinya!) Yang ditambahkan untuk tinju / unboxing yang lebih efisien sebelum obat generik. Mereka bekerja dalam koordinasi dengan System.TypedReference struct.

Ada juga __arglist, yang digunakan untuk daftar parameter panjang variabel.

Satu hal yang tidak diketahui banyak orang adalah System.WeakReference - kelas yang sangat berguna yang melacak objek tetapi masih memungkinkan pengumpul sampah untuk mengumpulkannya.

Fitur "tersembunyi" yang paling berguna adalah kata kunci hasil pengembalian. Itu tidak benar-benar tersembunyi, tetapi banyak orang tidak tahu tentang itu. LINQ dibangun di atas ini; ini memungkinkan untuk permintaan yang dieksekusi dengan menghasilkan mesin negara di bawah kap. Raymond Chen baru-baru ini memposting tentang detail internal yang kasar .

Judah Himango
sumber
2
Detail lebih lanjut tentang kata kunci tidak berdokumen oleh Peter Bromberg . Saya masih belum mengerti jika ada alasan untuk menggunakannya.
HuBeZa
@HuBeZa dengan munculnya obat generik, tidak banyak (ada?) Alasan bagus untuk menggunakan __refType, __makeref, dan __refvalue. Ini digunakan terutama untuk menghindari tinju sebelum obat generik dalam. NET 2.
Judah Gabriel Himango
Matt, dengan diperkenalkannya obat generik di .NET 2, ada sedikit alasan untuk menggunakan kata kunci ini, karena tujuannya adalah untuk menghindari tinju ketika berhadapan dengan tipe nilai. Lihat tautan oleh HuBeZa, dan lihat juga codeproject.com/Articles/38695/UnCommon-C-keywords-A-Look#ud
Judah Gabriel Himango
185

Serikat pekerja (jenis memori yang dibagikan C ++) dalam C # murni dan aman

Tanpa beralih ke mode dan pointer yang tidak aman, Anda dapat meminta anggota kelas berbagi ruang memori di kelas / struct. Diberi kelas berikut:

[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;
}

Anda dapat mengubah nilai-nilai bidang byte dengan memanipulasi bidang Int32 dan sebaliknya. Misalnya, program ini:

    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);
    }

Output ini:

2147483647
FF FF FF 7F
65535

cukup tambahkan menggunakan System.Runtime.InteropServices;

ZeroBugBounce
sumber
7
@ George, bekerja dengan sangat baik ketika Anda berkomunikasi dengan aplikasi lawas melalui soket menggunakan deklarasi c union.
scottm
2
Ada juga yang berarti untuk mengatakan int dan mengapung pada offset 0. Itu yang Anda butuhkan jika Anda ingin memanipulasi angka floating point sebagai bit mask, yang kadang-kadang Anda inginkan. Apalagi jika Anda ingin mempelajari hal-hal baru tentang angka floating point.
John Leidegren
2
Hal yang mengganggu tentang ini adalah jika Anda akan menggunakan ini adalah struct kompiler akan memaksa Anda untuk mengatur SEMUA variabel dalam fungsi init. Jadi jika Anda memiliki: public A (int int32) {Int32 = int32; } itu akan melempar "Field 'One' harus sepenuhnya ditugaskan sebelum kontrol dikembalikan ke pemanggil", jadi Anda harus mengatur Satu = Dua = Tiga = Empat = 0; demikian juga.
manixrock
2
Ini memiliki kegunaannya, sebagian besar dengan data biner. Saya menggunakan "Pixel" struct dengan int32 @ 0, dan empat byte untuk empat komponen @ 0, 1, 2, dan 3. Bagus untuk memanipulasi data gambar dengan cepat dan mudah.
Snarf
57
Peringatan: Pendekatan ini tidak memperhitungkan endianness. Itu berarti kode C # Anda tidak akan berjalan dengan cara yang sama di semua mesin. Pada CPU little-endian (yang menyimpan byte paling signifikan pertama), perilaku yang ditunjukkan akan digunakan. Tetapi pada CPU big-endian, byte akan keluar terbalik dari apa yang Anda harapkan. Waspadalah bagaimana Anda menggunakan ini dalam kode produksi - kode Anda mungkin tidak portabel untuk perangkat seluler tertentu dan perangkat keras lainnya, dan mungkin pecah dengan cara yang tidak jelas (misalnya dua file seolah-olah dalam format yang sama tetapi sebenarnya dengan urutan byte terbalik).
Ray Burns
176

Menggunakan @ untuk nama variabel yang merupakan kata kunci.

var @object = new object();
var @string = "";
var @if = IpsoFacto(); 
Mark Cidade
sumber
38
Mengapa Anda ingin menggunakan kata kunci sebagai nama variabel? Menurut saya ini akan membuat kode menjadi kurang mudah dibaca dan dikaburkan.
Jon
41
Nah, alasannya ada di sana adalah bahwa CLI membutuhkannya untuk interoperabilitas dengan bahasa lain yang mungkin menggunakan kata kunci C # sebagai nama anggota
Mark Cidade
69
Jika Anda ingin menggunakan asp.net MVC HTML helper dan mendefinisikan kelas HTML, Anda akan senang mengetahui bahwa Anda dapat menggunakan @class sehingga tidak akan dikenali sebagai kata kunci kelas
Boris Callens
31
Sangat bagus untuk metode ekstensi. public static void DoSomething (bilah ini @ ini, string foo) {...}
Jonathan C Dickinson
45
@zihotki: Salah. var a = 5; Console.WriteLine (@a); Cetakan 5
SLaks
168

Jika Anda ingin keluar dari program Anda tanpa memanggil blok atau penyelesai akhirnya gunakan FailFast :

Environment.FailFast()
Jan Bannister
sumber
12
Perhatikan bahwa metode ini juga membuat dump memori dan menulis pesan ke log kesalahan Windows.
RickNZ
1
Perlu dicatat bahwa tidak ada finalizer atau aplikasi domain yang membongkar acara yang akan dipanggil saat metode ini digunakan ...
AwkwardCoder
1
Memberi +1 untuk petunjuk, tetapi ini bukan C #, ini adalah BCL dari .NET.
Abel
System.Diagnostics.Process.GetCurrentProcess (). Kill () lebih cepat
Tolgahan Albayrak
153

Mengembalikan jenis anonim dari metode dan mengakses anggota tanpa refleksi.

// 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;
}
denis phillips
sumber
42
Itu benar-benar tidak membuat Anda apa-apa. Ini sebenarnya berbahaya. Bagaimana jika GetUserTuple dimodifikasi untuk mengembalikan beberapa jenis? Para pemain akan gagal pada saat run time. Salah satu hal hebat tentang C # /. Net adalah pengecekan waktu kompilasi. Akan jauh lebih baik untuk hanya membuat tipe baru.
Jason Jackson
9
@ Alasan saya mengatakan itu mungkin tidak berguna tetapi mengejutkan (dan saya pikir disembunyikan).
denis phillips
31
Meskipun keren, ini sepertinya pilihan desain yang agak buruk. Anda pada dasarnya mendefinisikan jenis anonim di dua tempat. Pada saat itu, cukup deklarasikan struct nyata dan gunakan secara langsung.
Paul Alexander
6
@ George: konvensi semacam itu akan disebut ... struct?
R. Martinho Fernandes
2
Trik ini dinamai 'cast by sample' dan itu tidak akan berfungsi jika metode yang mengembalikan tipe anonim terletak di rakitan lain.
desco
146

Inilah yang bermanfaat untuk ekspresi reguler dan jalur file:

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

@ Memberitahu kompiler untuk mengabaikan karakter escape dalam sebuah string.

Patrick
sumber
27
Juga, konstanta @ menerima baris baru di dalamnya. Sempurna saat menetapkan skrip multiline ke string.
Tor Haugen
11
Jangan lupa juga untuk menghindari tanda kutip cukup dengan menggandakannya, dengan kata lain. [code] var candy = @ "Saya suka" "red" "candy can."; [/ code]
Dave
5
Saya cenderung membangun jalur dengan Path.Combine. Saya pasti menggunakan @ untuk regex!
Dan McClain
6
@baru juga merupakan variabel dan bukan kata kunci: @ini, @int, @return, @interface ... seterusnya :)
IAbstract
Yang ini tidak mendekati: Tapi apa saja fitur atau trik paling tersembunyi dari C # yang bahkan penggemar C #, pecandu, ahli nyaris tidak tahu?
publicgk
141

Mixin. Pada dasarnya, jika Anda ingin menambahkan fitur ke beberapa kelas, tetapi tidak dapat menggunakan satu kelas dasar untuk semua kelas tersebut, mintalah setiap kelas untuk mengimplementasikan antarmuka (tanpa anggota). Kemudian, tulis metode ekstensi untuk antarmuka , yaitu

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

Tentu saja, beberapa kejelasan dikorbankan. Tapi berhasil!

Dmitri Nesteruk
sumber
4
Ya saya pikir ini adalah kekuatan sebenarnya dari metode ekstensi. Mereka pada dasarnya memungkinkan untuk implementasi metode antarmuka.
John Bubriski
Ini juga berguna jika Anda menggunakan NHibernate (atau Castle ActiveRecord) dan Anda harus menggunakan antarmuka untuk koleksi Anda. Dengan cara ini Anda bisa memberi perilaku ke antarmuka koleksi.
Ryan Lundy
Itulah dasarnya bagaimana semua metode LINQ diimplementasikan, sebagai catatan.
WCWedin
Berikut ini tautan yang membahas tentang apa yang saya sebutkan di atas, menggunakan metode ekstensi dengan antarmuka pengumpulan di NHibernate atau Castle ActiveRecord: devlicio.us/blogs/billy_mccafferty/archive/2008/09/03/…
Ryan Lundy
7
Kalau saja mereka mengizinkan properti ekstensi !!!! Saya benci harus menulis metode ekstensi yang memohon untuk menjadi properti read-only ....
John Gibb
130

Tidak yakin mengapa ada orang yang ingin menggunakan Nullable <bool>. :-)

Benar, Salah, FileNotFound ?

Michael Stum
sumber
87
jika mengharapkan pengguna untuk menjawab ya tidak ada pertanyaan maka null akan sesuai jika pertanyaan belum dijawab
Omar Kooheji
22
Jenis nullable berguna untuk interaksi dengan database di mana kolom tabel sering nullable.
tuinstoel
11
Ya, Tidak, Maybee?
Dan Blair
21
Menyimpan nilai-nilai kotak centang ThreeState
Shimmy Weitzhandler
8
Seperti dalam SQL: Ya / tidak / tidak dikenal.
erikkallen
116

Yang ini tidak "disembunyikan" sebanyak itu salah namanya.

Banyak perhatian diberikan pada algoritme "peta", "kurangi", dan "filter". Apa yang kebanyakan orang tidak sadari adalah. NET 3.5 menambahkan ketiga algoritma ini, tetapi memberi mereka nama yang sangat SQL-ish, berdasarkan pada fakta bahwa mereka adalah bagian dari LINQ.

"map" => Pilih
Mengubah data dari satu formulir ke bentuk lain

"kurangi" => Agregat
Agregat Nilai agregat menjadi satu hasil

"filter" => Di mana
Memfilter data berdasarkan kriteria

Kemampuan untuk menggunakan LINQ untuk melakukan pekerjaan inline pada koleksi yang digunakan untuk mengambil iterasi dan persyaratan bisa sangat berharga. Perlu dipelajari bagaimana semua metode ekstensi LINQ dapat membantu membuat kode Anda jauh lebih ringkas dan mudah dikelola.

Brad Wilson
sumber
1
Pilih juga bertindak seperti fungsi "kembali" di monads. Lihat stackoverflow.com/questions/9033/hidden-features-of-c#405088
Mark Cidade
1
Menggunakan "pilih" hanya diperlukan jika Anda menggunakan sintaks SQLish. Jika Anda menggunakan sintaksis metode ekstensi - someCollection.Where (item => item.Price> 5.99M) - penggunaan pernyataan pilihan tidak diperlukan.
Brad Wilson
7
@Brad, itu (di mana) adalah operasi filter. Coba lakukan operasi peta tanpa pilih ...
Eloff
2
LINQ adalah hal besar yang terjadi pada C # dalam pendapat saya: stackoverflow.com/questions/2398818/…
Leniel Maccaferri
1
Tanda tangan terkecil Aggregate adalah fungsi "mengurangi", tanda tangan tengah Agregat adalah fungsi "lipat" yang jauh lebih kuat!
Brett Widmeier
115
Environment.NewLine

untuk baris baru independen sistem.

nt.
sumber
10
Yang menyebalkan tentang ini, adalah tidak dimasukkan ke dalam kerangka ringkas.
Stormenet
14
Nilainya menunjukkan bahwa ini khusus untuk platform host aplikasi - jadi jika Anda membuat data yang ditujukan untuk sistem lain, Anda harus menggunakan \ n atau \ r \ n dengan tepat.
Mesh
Ini adalah bagian dari BCL dari .NET, bukan fitur C # per se.
Abel
111

Jika Anda mencoba menggunakan kurung keriting di dalam ekspresi String.Format ...

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"
Portman
sumber
19
@ Kirralessa: Sebenarnya, ya, itu kawat gigi, tapi "kurung keriting" adalah nama alternatif bagi mereka. [dan ]adalah kurung kotak, dan <dan >adalah kurung sudut. Lihat en.wikipedia.org/wiki/Bracket .
icktoofay
4
Anda benar. Tetapi ketika saya berkomentar, itu tidak mengatakan tanda kurung "keriting".
Ryan Lundy
2
Sangat bagus untuk ditunjukkan. Ingat String.Format pertama saya terlihat seperti: String.Format ("{0} Saya dalam kurung keriting {1} {2} {3}", "{", "}", 3, "blind mice"); Setelah saya mengetahui bahwa melarikan diri ini dilakukan dengan menggunakan {{dan}} saya sangat senang :)
Gertjan
Muahahahaa ... Pemrograman sudah 3 tahun di .Net dan saya tidak tahu yang ini. : D
Arnis Lapsa
"keriting" kurung bertindak mirip dengan urutan melarikan diri ??
Pratik
104
  1. ?? - operator penggabungan
  2. using ( statement / directive ) - kata kunci hebat yang bisa digunakan lebih dari sekadar menelepon Buang
  3. readonly - harus digunakan lebih banyak
  4. netmodules - sayang sekali tidak ada dukungan di Visual Studio
Doctor Jones
sumber
6
menggunakan juga dapat digunakan untuk alias namespace panjang ke string yang lebih nyaman, yaitu: menggunakan ZipEncode = MyCompany.UtilityCode.Compression.Zip.Encoding; Masih ada lagi di sini: msdn.microsoft.com/en-us/library/sf0df423.aspx
Dave R.
2
Ini sebenarnya bukan hal yang sama. Saat memanggil Buang, Anda dapat menggunakan statemen penggunaan, saat aliasing tipe yang Anda gunakan menggunakan arahan.
Øyvind Skaar
2
Kalau-kalau Anda ingin nama ke # 1 (seperti yang Anda lakukan dengan operator ternary), ?? disebut operator penggabungan nol.
J. Steen
4
@LucasAardvark: Seperti yang disebutkan J Steen, itu disebut operator penggabungan nol. Cari itu!
Kokos
1
Untuk mencari ?? operator di google try: google.com/search?q=c%23+%3F%3F+operator
backslash17
103

@ Id, saya agak enggan untuk memposting ini karena ini sedikit lebih dari sekadar nitpicking. Namun, saya akan menunjukkan bahwa dalam sampel kode Anda:

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

Jika Anda akan menggunakan 'apa adanya', mengapa harus diikuti dengan pemain aman menggunakan 'sebagai'? Jika Anda sudah memastikan bahwa obj memang MyClass, pemain standar rawa:

c = (MyClass)obj

... tidak akan pernah gagal.

Demikian pula, Anda bisa mengatakan:

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

Saya tidak cukup tahu tentang. NET innards untuk memastikan, tetapi insting saya mengatakan kepada saya bahwa ini akan memotong maksimum dua jenis operasi pemain ke maksimum satu. Kemungkinan besar tidak akan merusak bank pemrosesan; secara pribadi, saya pikir bentuk terakhir terlihat lebih bersih juga.

Dogmang
sumber
16
Jika gips ke tipe yang tepat (gips ke "A" ketika objek adalah "A", bukan berasal dari itu), gips lurus ~ 3x LEBIH CEPAT daripada "sebagai". Ketika casting tipe turunan (cast ke "A" ketika objek adalah "B", yang berasal dari "A"), cast lurus ~ 0,1x lebih lambat dari "as". "Adalah", lalu "seperti" itu konyol.
P Ayah
2
Tidak, tetapi Anda dapat menulis "jika ((c = obj sebagai MyClass)! = Null)".
Dave Van den Eynde
10
isdan astidak akan melakukan gips pengguna. Jadi, kode di atas bertanya kepada isoperator apakah obj diturunkan dari MyClass (atau memiliki sistem terdefinisi yang ditetapkan pemain). Juga isgagal null. Kedua kasus tepi ini mungkin penting untuk kode Anda. Misalnya, Anda mungkin ingin menulis: if( obj == null || obj is MyClass ) c = (MyClass)obj; Tapi ini sangat berbeda dari: try { c = (MyClass)obj; } catch { }karena yang pertama tidak akan melakukan konversi yang ditentukan pengguna, tetapi yang terakhir akan. Tanpa nullcek, mantan juga akan tidak diatur csaat objini null.
Adam Luter
2
Dalam IL, para pemain pergi ke CASTCLASS tetapi sebagai / sedang pergi ke instruksi ISINST.
John Gibb
5
Saya menjalankan tes untuk ini, casting IEnumerable<int>ke List<int>, dan casting object( new object()) untuk IEnumerable<int>, untuk memastikan tidak ada kesalahan: pemain langsung: 5.43ns, is-> sebagai pemain: 6.75ns, sebagai pemain: 5.69ns. Kemudian menguji gips yang tidak valid: gips langsung: 3125000ns, sebagai gips: 5.41ns. Kesimpulan: berhenti mengkhawatirkan faktor 1%, dan pastikan Anda menggunakan adalah / seperti ketika para pemain mungkin tidak valid, menyebabkan pengecualian (juga jika ditangani) SANGAT lambat dibandingkan dengan casting, kita berbicara tentang faktor 578000 lebih lambat. Ingatlah bahwa bagian terakhir, sisanya tidak masalah (.Net FW 4.0, rilis build)
Aidiakapi
98

Mungkin bukan teknik yang canggih, tapi yang saya lihat sepanjang waktu itu membuat saya gila:

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

dapat diringkas menjadi:

x = (x==1) ? 2 : 3;
JasonS
sumber
10
Operator ternary telah dilarang di grup saya. Beberapa orang tidak menyukainya, meskipun saya tidak pernah mengerti mengapa.
Justin R.
13
Saya kira karena itu bukan hal yang sama, menjadi operator bukan pernyataan. Saya lebih suka pendekatan pertama sendiri. Ini lebih konsisten dan mudah diperluas. Operator tidak dapat berisi pernyataan, sehingga saat Anda harus memperluas tubuh, Anda harus mengkonversi bahwa operator ternary untuk pernyataan jika
Kervin
16
dapat diringkas menjadi x ++; Oke, tidak ada gunanya ^^
François
5
@Guillaume: Untuk menjelaskan semua nilai x: x = 2 + System.Math.Min (1, System.Math.Abs ​​(x-1));
mbeckish
38
Ini benar-benar disebut "operator kondisional" - itu adalah sebuah operator ternary karena dibutuhkan tiga argumen. en.wikipedia.org/wiki/Conditional_operator
Blorgbeard keluar