Apa metode ekstensi favorit Anda untuk C #? (codeplex.com/extensionoverflow)

478

Mari buat daftar jawaban tempat Anda memposting metode ekstensi favorit dan istimewa Anda .

Syaratnya adalah bahwa kode lengkap harus diposting dan contoh dan penjelasan tentang cara menggunakannya.

Berdasarkan minat yang tinggi pada topik ini saya telah menyiapkan Proyek Sumber Terbuka yang disebut extensionoverflow pada Codeplex .

Harap tandai jawaban Anda dengan penerimaan untuk memasukkan kode ke proyek Codeplex.

Silakan kirim kode sumber lengkap dan bukan tautan.

Berita Codeplex:

24.08.2010 Halaman Codeplex sekarang ada di sini: http://extensionoverflow.codeplex.com/

11.11.2008 XmlSerialize / XmlDeserialize sekarang Diimplementasikan dan Unit Diuji .

11.11.2008 Masih ada ruang untuk lebih banyak pengembang. ;-) Bergabunglah SEKARANG!

11.11.2008 Kontributor ketiga bergabung dengan ExtensionOverflow , selamat datang di BKristensen

11.11.2008 FormatWith sekarang Diimplementasikan dan Unit Diuji .

09.11.2008 Kontributor kedua bergabung dengan ExtensionOverflow . selamat datang untuk chakrit .

09.11.2008 Kami membutuhkan lebih banyak pengembang. ;-)

09.11.2008 ThrowIfArgumentIsNull di Sekarang Diimplementasikan dan Unit Diuji pada Codeplex.

bovium
sumber
Sekarang kode pertama dikomit ke situs Codeplex.
bovium
Erik sayangnya semuanya dimulai sekarang pada codeplex. Silakan bergabung.
bovium
3
Terlihat bagus. Saya punya komentar tentang penamaan kelas statis. Memberi mereka <type> Ekstensi tidak terlalu informatif. Sebagai contoh, StringExtensions menampung item pemformatan dan xml. Saya pikir lebih baik memberi nama kelas dengan alasan Anda memperluas tipe itu. Misalnya UnixDateTimeConversions. Anda bisa menebaknya memegang metode untuk mengkonversi ke dan dari waktu Unix. Hanya pemikiran saja!
ecoffey
Periksa URL ini untuk informasi lebih lanjut tentang C # Metode Ekstensi planetofcoders.com/c-extension-methods
Gaurav Agrawal

Jawaban:

232
public static bool In<T>(this T source, params T[] list)
{
  if(null==source) throw new ArgumentNullException("source");
  return list.Contains(source);
}

Izinkan saya untuk mengganti:

if(reallyLongIntegerVariableName == 1 || 
    reallyLongIntegerVariableName == 6 || 
    reallyLongIntegerVariableName == 9 || 
    reallyLongIntegerVariableName == 11)
{
  // do something....
}

and

if(reallyLongStringVariableName == "string1" || 
    reallyLongStringVariableName == "string2" || 
    reallyLongStringVariableName == "string3")
{
  // do something....
}

and

if(reallyLongMethodParameterName == SomeEnum.Value1 || 
    reallyLongMethodParameterName == SomeEnum.Value2 || 
    reallyLongMethodParameterName == SomeEnum.Value3 || 
    reallyLongMethodParameterName == SomeEnum.Value4)
{
  // do something....
}

Dengan:

if(reallyLongIntegerVariableName.In(1,6,9,11))
{
      // do something....
}

and

if(reallyLongStringVariableName.In("string1","string2","string3"))
{
      // do something....
}

and

if(reallyLongMethodParameterName.In(SomeEnum.Value1, SomeEnum.Value2, SomeEnum.Value3, SomeEnum.Value4)
{
  // do something....
}
Winston Smith
sumber
2
Nah itu mengkompilasi jika Anda menggunakan System.Linq;
Ryu
11
Mungkin "EqualsAnyOf" akan menjadi nama yang lebih baik daripada "In"?
Tom Bushell
10
Saya tidak yakin saya menyukainya - Saya suka singkatnya In, tapi mungkin IsInakan lebih baik.
Winston Smith
50
Menggunakan metode Contains yang sama: (new [] {1, 2, 3}). Contains (a)
Max Toro
4
Saya memikirkan In<T>(...)juga dan menemukan itu menjadi metode ekstensi paling berguna di luar perpustakaan standar. Tapi saya berselisih dengan namanya In. Nama metode seharusnya menggambarkan apa yang dilakukannya, tetapi Intidak melakukannya. Saya sudah menyebutnya IsAnyOf<T>(...), tapi saya kira IsIn<T>(...)akan cukup juga.
JBSnorro
160

Saya memiliki berbagai metode ekstensi dalam proyek MiscUtil saya (sumber lengkap tersedia di sana - saya tidak akan mengulanginya di sini). Favorit saya, beberapa di antaranya melibatkan kelas lain (seperti rentang):

Barang tanggal dan waktu - kebanyakan untuk tes unit. Tidak yakin saya akan menggunakannya dalam produksi :)

var birthday = 19.June(1976);
var workingDay = 7.Hours() + 30.Minutes();

Berkisar dan melangkah - terima kasih banyak kepada Marc Gravell untuk hal - hal operatornya yang memungkinkan ini:

var evenNaturals = 2.To(int.MaxValue).Step(2);
var daysSinceBirth = birthday.To(DateTime.Today).Step(1.Days());

Perbandingan:

var myComparer = ProjectionComparer.Create(Person p => p.Name);
var next = myComparer.ThenBy(p => p.Age);
var reversed = myComparer.Reverse();

Pemeriksaan argumen:

x.ThrowIfNull("x");

LINQ to XML diterapkan pada tipe anonim (atau tipe lain dengan properti yang sesuai):

// <Name>Jon</Name><Age>32</Age>
new { Name="Jon", Age=32}.ToXElements();
// Name="Jon" Age="32" (as XAttributes, obviously)
new { Name="Jon", Age=32}.ToXAttributes()

Dorong LINQ - akan terlalu lama untuk dijelaskan di sini, tetapi mencarinya.

Jon Skeet
sumber
1
Itu bagus! Anda harus memasangnya di Google Code atau CodePlex sehingga saya dapat mengirimkan beberapa tambalan kepada Anda :-) Saya berjanji ini akan terbaca :-P
chakrit
3
@Bovium: Anda sudah dapat melihat kode. Ikuti tautan di kalimat pertama - sumber lengkap ada di sana.
Jon Skeet
1
@Bovium: Saya lebih suka melakukannya sendiri, meletakkannya di code.google.com dan mengelola proyek sendiri, jika Anda tidak keberatan. Jelas Anda berada dalam lisensi untuk meletakkannya di Codeplex jika Anda mempertahankan atribusi yang sesuai, tetapi saya lebih baik mengatasinya sendiri segera kecuali Anda putus asa :)
Jon Skeet
1
@ Jon Skeet. Diletakkan di bawah lisensi MIT gratis untuk semua orang. Sumber komersial atau open. Mengapa tidak bergabung dan membuat perpustakaan metode ekstensi untuk publik.
bovium
1
Hanya karena saya melakukan banyak hal lain di perpustakaan itu. Anda boleh mengambil salinannya untuk proyek Anda, tetapi saya lebih suka menyimpan satu salinan di proyek saya juga.
Jon Skeet
147

string.Format pintas:

public static class StringExtensions
{
    // Enable quick and more natural string.Format calls
    public static string F(this string s, params object[] args)
    {
        return string.Format(s, args);
    }
}

Contoh:

var s = "The co-ordinate is ({0}, {1})".F(point.X, point.Y);

Untuk salin dan tempel cepat, buka di sini .

Apakah Anda tidak merasa lebih alami untuk mengetik "some string".F("param")bukan string.Format("some string", "param")?

Untuk nama yang lebih mudah dibaca , cobalah salah satu dari saran ini:

s = "Hello {0} world {1}!".Fmt("Stack", "Overflow");
s = "Hello {0} world {1}!".FormatBy("Stack", "Overflow");
s = "Hello {0} world {1}!".FormatWith("Stack", "Overflow");
s = "Hello {0} world {1}!".Display("Stack", "Overflow");
s = "Hello {0} world {1}!".With("Stack", "Overflow");

..

chakrit
sumber
11
Ini tentu saja pendek - tetapi tidak akan dapat dibaca oleh anggota baru tim Anda.
Jon Skeet
3
Saya pikir keterbacaan lebih penting dalam skema besar kode Anda daripada beberapa pernyataan singkat yang bisa dengan cepat dicari / ditanyakan.
chakrit
6
Secara pribadi saya ingin objek Formatter terpisah, yang BCL dapat menguraikan pola sekaligus dan menggunakan kembali. Itu akan meningkatkan keterbacaan dan kinerja. Saya sudah bertanya kepada tim BCL - kita akan lihat ...
Jon Skeet
3
Ini adalah metode ekstensi, tentu saja itu tidak akan dapat dibaca oleh anggota baru tim. Saya pikir itu ide dengan hal-hal lucu ini? Bagaimana lagi para anggota baru mengetahui seberapa pintar kita?
MarkJ
17
Ok ... Saya hanya pergi untuk menjalankan ini dan pergi dengan. Dengan - jadi Anda mendapatkan "Ini adalah {0}". Dengan ("tes") dan itu sangat mudah dibaca dan masuk akal. FYI
klkitchens
89

Apakah ini ada gunanya?

public static bool CoinToss(this Random rng)
{
    return rng.Next(2) == 0;
}

public static T OneOf<T>(this Random rng, params T[] things)
{
    return things[rng.Next(things.Length)];
}

Random rand;
bool luckyDay = rand.CoinToss();
string babyName = rand.OneOf("John", "George", "Radio XBR74 ROCKS!");
xyz
sumber
ini meniru fungsi pythons random.choice (seq). bagus.
Daren Thomas
6
Beberapa hal: Saya akan merekomendasikan yang OneOfharus menerima apa pun IList<T> . Kemudian Anda bisa selalu juga memiliki kelebihan yang membutuhkan paramsarg dan hanya melewati itu ke dalam IList<T>overload. Saya memberikan jawaban (jalan turun di bagian bawah sekarang) dengan NextBoolmetode yang mirip dengan Anda CoinToss, tetapi dengan kelebihan yang mengambil probabilityparameter (bagaimana jika saya ingin sesuatu terjadi 75% dari waktu?). Juga, pilih saja: kode contoh Anda akan melempar NullReferenceExceptionkarena randtidak pernah diinisialisasi.
Dan Tao
3
+1 Saya sangat suka ini, tetapi saya lebih suka CoinTossdiimplementasikan dengan rng.NextDouble() < .5karena .Next(int)dibuat secara internal .NextDouble()sehingga Anda akan menghemat gips, * dan cek.
Lasse Espeholt
76
public static class ComparableExtensions
{
  public static bool Between<T>(this T actual, T lower, T upper) where T : IComparable<T>
  {
    return actual.CompareTo(lower) >= 0 && actual.CompareTo(upper) < 0;
  }
}

Contoh:

if (myNumber.Between(3,7))
{
  // ....
}
CMS
sumber
19
Saya suka yang ini tetapi saya mencoba untuk memutuskan apakah benar untuk membuat batas memeriksa termasuk pada nilai minimum tetapi eksklusif pada nilai maksimal. Saya bertanya-tanya apakah itu akan membingungkan. 5. Antara (5,10) benar tetapi 5. Antara (1,5) salah. Bahkan tidak yakin bahwa pendamping dalam metode akan membantu. Apa?
Steve Hiner
12
Bukankah nama "IsBetween" lebih masuk akal? Juga mungkin membuat IsBetweenInclusive dan IsBetweenExclusive. Tidak tahu mana yang harus diambil untuk default.
fretje
2
@Steve: lebih masuk akal jika itu adalah ekstensi datetime.
Joel Coehoorn
16
Bagi saya antara menyiratkan: 5. Antara (5,10) mengembalikan false, dan 10. Antara (5,10) mengembalikan palsu juga. Itu terasa alami bagi saya.
Alex Baranosky
3
Bagi saya, banyak orang memiliki gagasan berbeda tentang apa yang alami. Karena hal ini mungkin harus secara eksplisit dinyatakan apa yang sedang digunakan (yaitu Inklusif vs Eksklusif), karena ini bisa menjadi sumber kesalahan yang sangat mudah.
David Miani
58

Metode ekstensi:

public static void AddRange<T, S>(this ICollection<T> list, params S[] values)
    where S : T
{
    foreach (S value in values)
        list.Add(value);
}

Metode ini berlaku untuk semua jenis dan memungkinkan Anda menambahkan berbagai item ke daftar sebagai parameter.

Contoh:

var list = new List<Int32>();
list.AddRange(5, 4, 8, 4, 2);
stiduck
sumber
15
Akan lebih baik karena IList ini <T>
21
Cukup gunakan initializer koleksi =>var list = new List<int>{5,4,8,4,2};
Arnis Lapsa
Mengapa tidak hanya memanggil Daftar <T> .AddRange (koleksi IEnumerable <T>) dalam metode Anda?
Rauhotz
8
@ Akan: Sebenarnya, yang terbaik adalah menerima ICollection<T>; maka itu juga bisa digunakan pada, misalnya, LinkedList<T>dan HashSet<T>, bukan hanya koleksi yang diindeks.
Dan Tao
2
Diedit untuk mengizinkan kovarians di pre-.net 4.0
BlueRaja - Danny Pflughoeft
55

Dengan segala cara menempatkan ini dalam proyek codeplex.

Serializing / Deserializing objek ke XML:

/// <summary>Serializes an object of type T in to an xml string</summary>
/// <typeparam name="T">Any class type</typeparam>
/// <param name="obj">Object to serialize</param>
/// <returns>A string that represents Xml, empty otherwise</returns>
public static string XmlSerialize<T>(this T obj) where T : class, new()
{
    if (obj == null) throw new ArgumentNullException("obj");

    var serializer = new XmlSerializer(typeof(T));
    using (var writer = new StringWriter())
    {
        serializer.Serialize(writer, obj);
        return writer.ToString();
    }
}

/// <summary>Deserializes an xml string in to an object of Type T</summary>
/// <typeparam name="T">Any class type</typeparam>
/// <param name="xml">Xml as string to deserialize from</param>
/// <returns>A new object of type T is successful, null if failed</returns>
public static T XmlDeserialize<T>(this string xml) where T : class, new()
{
    if (xml == null) throw new ArgumentNullException("xml");

    var serializer = new XmlSerializer(typeof(T));
    using (var reader = new StringReader(xml))
    {
        try { return (T)serializer.Deserialize(reader); }
        catch { return null; } // Could not be deserialized to this type.
    }
}
TWith2 gula
sumber
8
Saya akan tergoda untuk memanggil yang pertama ToXml()(seperti ToString())
Jay Bazuzi
1
Permintaan maaf kepada OP jika dia sengaja menulis seperti ini, tetapi penggunaan MemoryStreams DAN XmlReader / XmlWriter berlebihan. Kelas StringReader dan StringWriter sempurna untuk operasi ini.
Portman
2
Hati-hati, ini bukan threadsafe. Anda pasti harus menyinkronkan akses Anda ke kamus serialis statis.
Yann Schwartz
2
@Yann, @T, Jauh lebih mudah jika Anda hanya menambahkan atribut "utas statis". Kemudian cache baru akan dibuat per utas. Tidak perlu sinkronisasi.
Frank Krueger
1
@ Jonathan C Dickinson: Tampaknya dari dokumen MSDN di sini msdn.microsoft.com/en-us/library/… bahwa konstruktor yang digunakan (XmlSerializer (tipe) baru) tidak memiliki masalah kebocoran memori. Jadi mungkin kode caching tidak diperlukan?
slolife
46

ForEach untuk IEnumerables

public static class FrameworkExtensions
{
    // a map function
    public static void ForEach<T>(this IEnumerable<T> @enum, Action<T> mapFunction)
    {
        foreach (var item in @enum) mapFunction(item);
    }
}

Contoh naif:

var buttons = GetListOfButtons() as IEnumerable<Button>;

// click all buttons
buttons.ForEach(b => b.Click());

Contoh keren:

// no need to type the same assignment 3 times, just
// new[] up an array and use foreach + lambda
// everything is properly inferred by csc :-)
new { itemA, itemB, itemC }
    .ForEach(item => {
        item.Number = 1;
        item.Str = "Hello World!";
    });

catatan:

Ini tidak seperti Selectkarena Select mengharapkan fungsi Anda mengembalikan sesuatu seperti untuk mentransformasikannya ke daftar lain.

ForEach hanya memungkinkan Anda untuk mengeksekusi sesuatu untuk setiap item tanpa transformasi / manipulasi data.

Saya membuat ini sehingga saya dapat memprogram dalam gaya yang lebih fungsional dan saya terkejut bahwa List memiliki ForEach sementara IEnumerable tidak.

Masukkan ini dalam proyek codeplex

chakrit
sumber
13
Posting tentang mengapa ekstensi LINN's IEnumerable <T> tidak termasuk ForEach: stackoverflow.com/questions/317874/…
Neil
13
Saya sarankan membaca ini sebelum menggunakan metode: blogs.msdn.com/ericlippert/archive/2009/05/18/...
jpbochi
2
@jpbochi: Ini hanya demagogi Microsoft
abatishchev
1
@abatishchev Dan komentar Anda hanyalah prasangka terhadap Microsoft. Itu tidak membatalkan kata apa pun yang ditulis oleh Eric. Argumen seseorang tidak dibuat valid atau tidak valid hanya karena perusahaan tempat dia bekerja.
jpbochi
1
Ngomong-ngomong, izinkan saya menjelaskan satu hal. Saya tidak mengatakan Anda tidak harus menggunakan metode ekstensi ForEach ini. Saya hanya mengatakan bahwa Anda harus mempertimbangkan poin-poin yang diungkapkan Eric sebelum Anda memutuskan apakah akan menggunakannya atau tidak. Saya membacanya dan saya memutuskan untuk tidak menggunakannya. Anda bebas melakukan apa pun yang Anda inginkan dengan kode Anda.
jpbochi
43

Ekstensi konversi saya yang memungkinkan Anda melakukan:

int i = myString.To<int>();

Ini dia, seperti yang diposting di TheSoftwareJedi.com

public static T To<T>(this IConvertible obj)
{
  return (T)Convert.ChangeType(obj, typeof(T));
}

public static T ToOrDefault<T>
             (this IConvertible obj)
{
    try
    {
        return To<T>(obj);
    }
    catch
    {
        return default(T);
    }
}

public static bool ToOrDefault<T>
                    (this IConvertible obj,
                     out T newObj)
{
    try
    {
        newObj = To<T>(obj); 
        return true;
    }
    catch
    {
        newObj = default(T); 
        return false;
    }
}

public static T ToOrOther<T>
                       (this IConvertible obj,
                       T other)
{
  try
  {
      return To<T>obj);
  }
  catch
  {
      return other;
  }
}

public static bool ToOrOther<T>
                         (this IConvertible obj,
                         out T newObj,
                         T other)
{
    try
    {
        newObj = To<T>(obj);
        return true;
    }
    catch
    {
        newObj = other;
        return false;
    }
}

public static T ToOrNull<T>
                      (this IConvertible obj)
                      where T : class
{
    try
    {
        return To<T>(obj);
    }
    catch
    {
        return null;
    }
}

public static bool ToOrNull<T>
                  (this IConvertible obj,
                  out T newObj)
                  where T : class
{
    try
    {
        newObj = To<T>(obj);
        return true;
    }
    catch
    {
        newObj = null;
        return false;
    }
}

Anda dapat meminta default (memanggil konstruktor kosong atau "0" untuk angka) pada kegagalan, menentukan nilai "default" (saya menyebutnya "lain"), atau meminta nol (di mana T: kelas). Saya juga menyediakan kedua model pengecualian senyap, dan model TryParse khas yang mengembalikan bool yang mengindikasikan tindakan yang diambil, dan param yang keluar menyimpan nilai baru. Jadi kode kita dapat melakukan hal-hal seperti ini

int i = myString.To<int>();
string a = myInt.ToOrDefault<string>();
//note type inference
DateTime d = myString.ToOrOther(DateTime.MAX_VALUE);
double d;
//note type inference
bool didItGiveDefault = myString.ToOrDefault(out d);
string s = myDateTime.ToOrNull<string>();

Saya tidak bisa mendapatkan tipe Nullable untuk menggulung semuanya dengan sangat bersih. Saya mencoba sekitar 20 menit sebelum saya menyerah.

Perangkat LunakJedi
sumber
64
Secara pribadi, saya bukan penggemar kode yang mencoba / menangkap untuk menentukan hasilnya. Coba / tangkap harus digunakan untuk kesalahan yang terjadi di luar logika yang dimaksud, IMO. hmmmmm
Pure.Krome
Jika saya tidak ingin Anda menggunakan kode, saya tidak akan mempostingnya! :)
TheSoftwareJedi
Akhirnya sesuatu yang tak terlihat. Saya suka itu. :)
Arnis Lapsa
8
Anda setidaknya harus mengubah klausa "tangkap" untuk hanya menangkap pengecualian yang akan muncul oleh ChangeType () ketika tidak dapat "mengubah" referensi. Saya pikir Anda tidak ingin memiliki OutOfMemoryException, ExecutionEngineException, ThreadAbortException, atau sama-sama diperlakukan sebagai kesalahan konversi. Hal-hal itu kalau tidak akan cukup sulit untuk melacak kesalahan.
Christian.K
2
Saya percaya ToOrNullmemiliki perilaku yang sama persis ToOrDefault(yaitu, jika Anda memanggil ToOrDefaultjenis referensi dengan konversi yang tidak berhasil, itu akan kembali null). Tetapi yang lebih penting, sepertinya agak berlebihan bagi saya karena var s = myObject as stringmencapai hal yang sama dengan var s = myObject.ToOrNull<string>()- tetapi tanpa berpotensi harus menangkap InvalidCastException. Apakah saya melewatkan sesuatu?
Dan Tao
43

Saya memiliki metode ekstensi untuk mencatat pengecualian:

public static void Log(this Exception obj)
{
  //your logging logic here
}

Dan digunakan seperti ini:

try
{
    //Your stuff here
}
catch(Exception ex)
{
    ex.Log();
}

[maaf karena memposting dua kali; yang ke-2 dirancang lebih baik :-)]

Charlie
sumber
2
Harus membaca Log statis publik yang kosong (objek Pengecualian ini) {} mungkin?
Chris S
Saya pikir ini bagus untuk pengecualian BCL atau pihak ke-3, tetapi jika Anda memutar jenis pengecualian Anda sendiri, Anda bisa menempatkan logging di kelas pengecualian dasar Anda. Dengan begitu Anda tidak perlu mengingat untuk memanggil Log ().
si618
38
public static class StringExtensions {

    /// <summary>
    /// Parses a string into an Enum
    /// </summary>
    /// <typeparam name="T">The type of the Enum</typeparam>
    /// <param name="value">String value to parse</param>
    /// <returns>The Enum corresponding to the stringExtensions</returns>
    public static T EnumParse<T>(this string value) {
        return StringExtensions.EnumParse<T>(value, false);
    }

    public static T EnumParse<T>(this string value, bool ignorecase) {

        if (value == null) {
            throw new ArgumentNullException("value");
        }

        value = value.Trim();

        if (value.Length == 0) {
            throw new ArgumentException("Must specify valid information for parsing in the string.", "value");
        }

        Type t = typeof(T);

        if (!t.IsEnum) {
            throw new ArgumentException("Type provided must be an Enum.", "T");
        }

        return (T)Enum.Parse(t, value, ignorecase);
    }
}

Berguna untuk mengurai string menjadi Enum.

public enum TestEnum
{
    Bar,
    Test
}

public class Test
{
    public void Test()
    {
        TestEnum foo = "Test".EnumParse<TestEnum>();
    }
 }

Kredit diberikan kepada Scott Dorman

--- Edit untuk proyek Codeplex ---

Saya telah bertanya kepada Scott Dorman apakah dia akan keberatan jika kami menerbitkan kodenya di proyek Codeplex. Inilah jawaban yang saya dapat darinya:

Terima kasih atas informasi mengenai pos SO dan proyek CodePlex. Saya telah mengangkat jawaban Anda atas pertanyaan itu. Ya, kode ini secara efektif berada dalam domain publik yang saat ini berada di bawah Lisensi Terbuka CodeProject ( http://www.codeproject.com/info/cpol10.aspx ).

Saya tidak punya masalah dengan ini termasuk dalam proyek CodePlex, dan jika Anda ingin menambahkan saya ke proyek (nama pengguna adalah sdorman) saya akan menambahkan metode itu ditambah beberapa metode pembantu enum tambahan.

mlarsen
sumber
Skenario enum-parsing ini muncul setiap saat ... harus meletakkan ini di lib saya :-)
chakrit
Wow, saya telah menulis metode untuk memetakan string ke enum (baru mulai menggunakan .NET). Terima kasih, ini akan sangat membantu!
Kevin
4
Anda mungkin juga mempertimbangkan menamai ToEnum ini <> (), karena ia datang setelah objek.
Neil
Perhatikan bahwa Enum.TryParse <T> telah ditambahkan ke Net 4.0 - blogs.msdn.com/bclteam
Dan Diplo
1
Saya tidak berpikir metode ini harus menggunakan Trim. Memotong input harus menjadi tanggung jawab penelepon.
CodesInChaos
32

Saya menemukan ini cukup berguna:

public static class PaulaBean
{
    private static String paula = "Brillant";
    public static String GetPaula<T>(this T obj) {
        return paula;
    }
}

Anda dapat menggunakannya di CodePlex.

Juliet
sumber
2
Bisakah seseorang berbaik hati menjelaskannya kepada kita yang kurang berbakat?
jpbochi
hahaha Baru saja membaca artikel (komentar Joel di atas) - lucu benar, tetapi setelah berada di perahu yang sama (di ujung penerima, bukan di ujung Paula) itu hanya lucu melihat ke belakang! Pernah seorang kontraktor dibawa masuk untuk mengerjakan suatu proyek, saya ditunjuk sebagai desainer / pemimpin - dia tidak berada di bawah kendali langsung saya, tetapi ditugaskan pekerjaan dari daftar kerja tim saya. Atasan memuji dia sebagai orang yang brilian (bahkan mempekerjakannya lagi nanti sebagai Dev Lead!). Mereka tidak pernah sadar bahwa setiap bagian dari kode yang dia tulis atau rancang tidak membuatnya menjadi produksi dan semua harus ditulis ulang sepenuhnya dari awal oleh tim saya!
Wolf5370
31

DateTimeExtensions

Contoh:

DateTime firstDayOfMonth = DateTime.Now.First();
DateTime lastdayOfMonth = DateTime.Now.Last();
DateTime lastFridayInMonth = DateTime.Now.Last(DayOfWeek.Friday);
DateTime nextFriday = DateTime.Now.Next(DayOfWeek.Friday);
DateTime lunchTime = DateTime.Now.SetTime(11, 30);
DateTime noonOnFriday = DateTime.Now.Next(DayOfWeek.Friday).Noon();
DateTime secondMondayOfMonth = DateTime.Now.First(DayOfWeek.Monday).Next(DayOfWeek.Monday).Midnight();
CMS
sumber
5
Saya sarankan mengubah nama "SetTime" menjadi "WithTime" karena itu tidak benar-benar menetapkannya dalam nilai yang ada. Bagus sebaliknya.
Jon Skeet
28
DateTime.Now.First () - pertama apa? Itu hanya terlihat dari kode sampel.
mackenir
2
Sangat bagus. Tetapi setuju bahwa nama-nama itu bisa menjadi jauh lebih baik.
bovium
DateTime.Now.First akan cukup jelas di Intellisense jika metode ini didokumentasikan dengan baik.
Ryan Lundy
29

gitorious.org/cadenza adalah perpustakaan lengkap dari beberapa metode ekstensi paling berguna yang pernah saya lihat.

sontek
sumber
12 metode ekstensi yang cukup mendasar. Saya agak underwhelmed oleh batu tunggal.
mackenir
(Saya berbicara tentang versi yang dirilis, bukan yang Anda butuhkan untuk menggunakan kontrol sumber untuk mendapatkan)
mackenir
28

Ini adalah salah satu yang sering saya gunakan untuk memformat presentasi.

public static string ToTitleCase(this string mText)
{
    if (mText == null) return mText;

    System.Globalization.CultureInfo cultureInfo = System.Threading.Thread.CurrentThread.CurrentCulture;
    System.Globalization.TextInfo textInfo = cultureInfo.TextInfo;

    // TextInfo.ToTitleCase only operates on the string if is all lower case, otherwise it returns the string unchanged.
    return textInfo.ToTitleCase(mText.ToLower());
}
Venr
sumber
Whoah, penanganan Pokemon pengecualian akan menyembunyikan masalah seperti ThreadAbortException, dll. Harap tangkap sesuatu yang spesifik.
JBRWilkinson
28

Ini adalah to-and-from untuk angka Romawi. Tidak sering digunakan, tetapi bisa berguna. Pemakaian:

if ("IV".IsValidRomanNumeral())
{
   // Do useful stuff with the number 4.
}

Console.WriteLine("MMMDCCCLXXXVIII".ParseRomanNumeral());
Console.WriteLine(3888.ToRomanNumeralString());

Sumber:

    public static class RomanNumeralExtensions
    {
        private const int NumberOfRomanNumeralMaps = 13;

        private static readonly Dictionary<string, int> romanNumerals =
            new Dictionary<string, int>(NumberOfRomanNumeralMaps)
            {
                { "M", 1000 }, 
                { "CM", 900 }, 
                { "D", 500 }, 
                { "CD", 400 }, 
                { "C", 100 }, 
                { "XC", 90 }, 
                { "L", 50 }, 
                { "XL", 40 }, 
                { "X", 10 }, 
                { "IX", 9 }, 
                { "V", 5 }, 
                { "IV", 4 }, 
                { "I", 1 }
            };

        private static readonly Regex validRomanNumeral = new Regex(
            "^(?i:(?=[MDCLXVI])((M{0,3})((C[DM])|(D?C{0,3}))"
            + "?((X[LC])|(L?XX{0,2})|L)?((I[VX])|(V?(II{0,2}))|V)?))$", 
            RegexOptions.Compiled);

        public static bool IsValidRomanNumeral(this string value)
        {
            return validRomanNumeral.IsMatch(value);
        }

        public static int ParseRomanNumeral(this string value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            value = value.ToUpperInvariant().Trim();

            var length = value.Length;

            if ((length == 0) || !value.IsValidRomanNumeral())
            {
                throw new ArgumentException("Empty or invalid Roman numeral string.", "value");
            }

            var total = 0;
            var i = length;

            while (i > 0)
            {
                var digit = romanNumerals[value[--i].ToString()];

                if (i > 0)
                {
                    var previousDigit = romanNumerals[value[i - 1].ToString()];

                    if (previousDigit < digit)
                    {
                        digit -= previousDigit;
                        i--;
                    }
                }

                total += digit;
            }

            return total;
        }

        public static string ToRomanNumeralString(this int value)
        {
            const int MinValue = 1;
            const int MaxValue = 3999;

            if ((value < MinValue) || (value > MaxValue))
            {
                throw new ArgumentOutOfRangeException("value", value, "Argument out of Roman numeral range.");
            }

            const int MaxRomanNumeralLength = 15;
            var sb = new StringBuilder(MaxRomanNumeralLength);

            foreach (var pair in romanNumerals)
            {
                while (value / pair.Value > 0)
                {
                    sb.Append(pair.Key);
                    value -= pair.Value;
                }
            }

            return sb.ToString();
        }
    }
Jesse C. Slicer
sumber
Itu mengingatkan saya pada Python PEP 313, yang merupakan lelucon April Mop untuk memasukkan Roman Numeral literal di python: python.org/dev/peps/pep-0313
Torial
25

Cara mudah untuk menangani ukuran:

public static class Extensions {
    public static int K(this int value) {
        return value * 1024;
    }
    public static int M(this int value) {
        return value * 1024 * 1024;
    }
}

public class Program {
    public void Main() {
        WSHttpContextBinding serviceMultipleTokenBinding = new WSHttpContextBinding() {
            MaxBufferPoolSize = 2.M(), // instead of 2097152
            MaxReceivedMessageSize = 64.K(), // instead of 65536
        };
    }
}
Paolo Tedesco
sumber
Menurut pendapat saya ini adalah gaya pengkodean yang benar-benar buruk. Konstanta harus digunakan sebagai gantinya, bukan logika yang dikaburkan.
xxbbcc
24

Untuk Kontrol Winform:

/// <summary>
/// Returns whether the function is being executed during design time in Visual Studio.
/// </summary>
public static bool IsDesignTime(this Control control)
{
    if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
    {
        return true;
    }

    if (control.Site != null && control.Site.DesignMode)
    {
        return true;
    }

    var parent = control.Parent;
    while (parent != null)
    {
        if (parent.Site != null && parent.Site.DesignMode)
        {
            return true;
        }
        parent = parent.Parent;
    }
    return false;
}

/// <summary>
/// Sets the DropDownWidth to ensure that no item's text is cut off.
/// </summary>
public static void SetDropDownWidth(this ComboBox comboBox)
{
    var g = comboBox.CreateGraphics();
    var font = comboBox.Font;
    float maxWidth = 0;

    foreach (var item in comboBox.Items)
    {
        maxWidth = Math.Max(maxWidth, g.MeasureString(item.ToString(), font).Width);
    }

    if (comboBox.Items.Count > comboBox.MaxDropDownItems)
    {
        maxWidth += SystemInformation.VerticalScrollBarWidth;
    }

    comboBox.DropDownWidth = Math.Max(comboBox.Width, Convert.ToInt32(maxWidth));
}

Penggunaan IsDesignTime:

public class SomeForm : Form
{
    public SomeForm()
    {
        InitializeComponent();

        if (this.IsDesignTime())
        {
            return;
        }

        // Do something that makes the visual studio crash or hang if we're in design time,
        // but any other time executes just fine
    }
}

Penggunaan SetDropdownWidth:

ComboBox cbo = new ComboBox { Width = 50 };
cbo.Items.Add("Short");
cbo.Items.Add("A little longer");
cbo.Items.Add("Holy cow, this is a really, really long item. How in the world will it fit?");
cbo.SetDropDownWidth();

Saya lupa menyebutkan, jangan ragu untuk menggunakan ini pada Codeplex ...

fre0n
sumber
1
Seperti disebutkan, ini hanya untuk WinForms. Ini mungkin bekerja dengan WPF tetapi ada masalah (dijelaskan dalam komentar tentang WPF di msdn.microsoft.com/en-us/library/… ). Solusi terbaik untuk WPF yang saya temukan dijelaskan di geekswithblogs.net/lbugnion/archive/2009/09/05/… (meskipun, karena ini adalah properti statis, itu tidak benar-benar berfungsi sebagai metode ekstensi.)
scobi
23

ThrowIfArgumentIsNull adalah cara yang bagus untuk melakukan itu, cek nol yang harus kita semua lakukan.

public static class Extensions
{
    public static void ThrowIfArgumentIsNull<T>(this T obj, string parameterName) where T : class
    {
        if (obj == null) throw new ArgumentNullException(parameterName + " not allowed to be null");
    }
}

Di bawah ini adalah cara untuk menggunakannya dan berfungsi pada semua kelas di namespace Anda atau di mana pun Anda menggunakan namespace di dalamnya.

internal class Test
{
    public Test(string input1)
    {
        input1.ThrowIfArgumentIsNull("input1");
    }
}

Tidak masalah menggunakan kode ini pada proyek CodePlex .

bovium
sumber
Saya suka ini juga, Jon memilikinya di dalamnya, dan saya menggunakan sesuatu yang mirip dari Payung, bisa tahan untuk menjatuhkan bagian "ArgumentIs".
cfeduke
Ya! ini adalah metode ekstensi kewl juga :)
Pure.Krome
3
Jika Anda menggunakan ArgumentNullException-constructor dengan hanya 1 string-argumen, argumen itu harus hanya nama parameter, dan bukan pesan kesalahan. Jadi kode Anda akan terlihat seperti ini: if (obj == null) lempar ArgumentNullException baru (parameterName);
Tommy Carlier
Saya akan menggunakan default(T)ini dan menghapus persyaratan kelas.
Joel Coehoorn
1
@ Joel: Nilai non-default untuk tipe asli adalah argumen yang sah lebih sering daripada nilai nol. Memeriksa null berarti lebih masuk akal bagi saya daripada mengecek default. Tentu saja, saya hanya menyamaratakan seluruh gagasan dengan mengatakan Require.ThatArgument(input != null)atau Require.ThatArgument(personId > 0). Tidak membutuhkan kode lebih banyak, lebih fleksibel, dan terbaca dengan baik. Saya memiliki penggantian tambahan yang berfungsi ketika Anda ingin menyesuaikan pesan kesalahan atau pengecualian itu sendiri.
StriplingWarrior
22

Saya melewatkan pernyataan Dengan Visual Basic ketika pindah ke C #, jadi begini:

public static void With<T>(this T obj, Action<T> act) { act(obj); }

Dan inilah cara menggunakannya di C #:

someVeryVeryLonggggVariableName.With(x => {
    x.Int = 123;
    x.Str = "Hello";
    x.Str2 = " World!";
});

Menghemat banyak pengetikan!

Bandingkan ini dengan:

someVeryVeryLonggggVariableName.Int = 123;
someVeryVeryLonggggVariableName.Str = "Hello";
someVeryVeryLonggggVariableName.Str2 = " World!";

dimasukkan ke dalam proyek codeplex

chakrit
sumber
4
Tebakan saja, tetapi pikirkan tentang apa yang terjadi jika T Anda adalah sebuah struct.
Rauhotz
5
Saya juga menggunakan sintaks initializer properti c # 3.0 sedapat mungkin untuk mencapai hasil yang sama.
Steve
3
@chakrit, ini sebuah contoh. Ini hanya berlaku saat membuat objek Tombol n = Tombol baru {Nama = "Button1", Lebar = 100, Tinggi = 20, Diaktifkan = benar};
Steve
1
Ini akan berguna ketika Anda memiliki banyak acara untuk dihubungkan, karena sintaks initializer properti C # tidak mendukung acara.
Gabe
1
ini juga berguna di luar inisialisasi properti, karena Anda hanya dapat menggunakannya saat membuat objek baru. ekstensi ini dapat bekerja pada objek yang dibuat sebelumnya.
Brady Moritz
18

Mengambil camelCaseWord atau PascalCaseWord dan "wordifies" itu, yaitu camelCaseWord => unta Case Word

public static string Wordify( this string camelCaseWord )
{
    // if the word is all upper, just return it
    if( !Regex.IsMatch( camelCaseWord, "[a-z]" ) )
        return camelCaseWord;

    return string.Join( " ", Regex.Split( camelCaseWord, @"(?<!^)(?=[A-Z])" ) );
}

Saya sering menggunakannya bersamaan dengan Capitalize

public static string Capitalize( this string word )
{
    return word[0].ToString( ).ToUpper( ) + word.Substring( 1 );
}

Contoh penggunaan

SomeEntityObject entity = DataAccessObject.GetSomeEntityObject( id );
List<PropertyInfo> properties = entity.GetType().GetPublicNonCollectionProperties( );

// wordify the property names to act as column headers for an html table or something
List<string> columns = properties.Select( p => p.Name.Capitalize( ).Wordify( ) ).ToList( );

Bebas digunakan dalam proyek codeplex

μBio
sumber
Agregat di Kapitalisasi sangat buruk untuk kinerja, karena itu menciptakan banyak contoh string. Mengapa tidak menggunakan kata. Substring (1) sebagai gantinya?
Thomas Levesque
17

Saya menemukan ini membantu

public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> pSeq)
{
    return pSeq ?? Enumerable.Empty<T>();
}

Ini menghapus cek nol dalam kode panggilan. Sekarang Anda bisa melakukannya

MyList.EmptyIfNull().Where(....)
Vasu Balakrishnan
sumber
Ya, jika seseorang lupa "Null Object Pattern" metode ini berguna untuk menambalnya. Koleksi tidak boleh nol.
Pavel Hodek
16

Konversi ganda menjadi string yang diformat menggunakan budaya yang ditentukan:

public static class ExtensionMethods 
{
  public static string ToCurrency(this double value, string cultureName)
  {
    CultureInfo currentCulture = new CultureInfo(cultureName);
    return (string.Format(currentCulture, "{0:C}", value));
  }
}

Contoh:

double test = 154.20;
string testString = test.ToCurrency("en-US"); // $154.20
CMS
sumber
13
Anda harus menggunakan Desimal untuk mata uang lain yang akan Anda dapatkan masalah pembulatannya
Andrew Bullock
Bagaimana dengan menggunakan Enum dalam parameter bukannya string biasa
Rulas
15

Di bawah ini adalah metode ekstensi yang mengadaptasi kode Rick Strahl (dan komentar juga) untuk menghentikan Anda harus menebak atau membaca tanda urutan byte dari array byte atau file teks setiap kali Anda mengonversinya menjadi string.

Cuplikan memungkinkan Anda melakukan:

byte[] buffer = File.ReadAllBytes(@"C:\file.txt");
string content = buffer.GetString();

Jika Anda menemukan bug, silakan tambahkan ke komentar. Jangan ragu untuk memasukkannya ke dalam proyek Codeplex.

public static class Extensions
{
    /// <summary>
    /// Converts a byte array to a string, using its byte order mark to convert it to the right encoding.
    /// Original article: http://www.west-wind.com/WebLog/posts/197245.aspx
    /// </summary>
    /// <param name="buffer">An array of bytes to convert</param>
    /// <returns>The byte as a string.</returns>
    public static string GetString(this byte[] buffer)
    {
        if (buffer == null || buffer.Length == 0)
            return "";

        // Ansi as default
        Encoding encoding = Encoding.Default;       

        /*
            EF BB BF    UTF-8 
            FF FE UTF-16    little endian 
            FE FF UTF-16    big endian 
            FF FE 00 00 UTF-32, little endian 
            00 00 FE FF UTF-32, big-endian 
         */

        if (buffer[0] == 0xef && buffer[1] == 0xbb && buffer[2] == 0xbf)
            encoding = Encoding.UTF8;
        else if (buffer[0] == 0xfe && buffer[1] == 0xff)
            encoding = Encoding.Unicode;
        else if (buffer[0] == 0xfe && buffer[1] == 0xff)
            encoding = Encoding.BigEndianUnicode; // utf-16be
        else if (buffer[0] == 0 && buffer[1] == 0 && buffer[2] == 0xfe && buffer[3] == 0xff)
            encoding = Encoding.UTF32;
        else if (buffer[0] == 0x2b && buffer[1] == 0x2f && buffer[2] == 0x76)
            encoding = Encoding.UTF7;

        using (MemoryStream stream = new MemoryStream())
        {
            stream.Write(buffer, 0, buffer.Length);
            stream.Seek(0, SeekOrigin.Begin);
            using (StreamReader reader = new StreamReader(stream, encoding))
            {
                return reader.ReadToEnd();
            }
        }
    }
}
Chris S
sumber
Metode yang sangat berguna, tapi saya rasa itu tidak perlu dan metode ekstensi.
Pop Catalin
Jika Anda sedang menulis editor teks mungkin waran metode ekstensi, tapi saya setuju sebagian besar waktu itu mungkin tidak lebih dari sebuah metode private static
Chris S
15

Ini yang baru saya buat hari ini.

// requires .NET 4

public static TReturn NullOr<TIn, TReturn>(this TIn obj, Func<TIn, TReturn> func,
        TReturn elseValue = default(TReturn)) where TIn : class
    { return obj != null ? func(obj) : elseValue; }

// versions for CLR 2, which doesn't support optional params

public static TReturn NullOr<TIn, TReturn>(this TIn obj, Func<TIn, TReturn> func,
        TReturn elseValue) where TIn : class
    { return obj != null ? func(obj) : elseValue; }
public static TReturn NullOr<TIn, TReturn>(this TIn obj, Func<TIn, TReturn> func)
        where TIn : class
    { return obj != null ? func(obj) : default(TReturn); }

Ini memungkinkan Anda melakukan ini:

var lname = thingy.NullOr(t => t.Name).NullOr(n => n.ToLower());

yang lebih lancar dan (IMO) lebih mudah dibaca daripada ini:

var lname = (thingy != null ? thingy.Name : null) != null
    ? thingy.Name.ToLower() : null;
Scott Bilas
sumber
1
Bagaimana jika saya mau thingy.NullOr(t => t.Count), di mana Countint? Anda harus mengembalikan default(TReturn)daripada nol, dengan begitu Anda tidak akan memerlukan classbatasan dan itu akan bekerja untuk tipe nilai juga
Thomas Levesque
2
TIn harus diminta menjadi kelas, jika tidak seluruh metode ekstensi ini tidak masuk akal (tipe nilai tidak boleh nol). Dan contoh Anda dengan t.Count tidak bekerja dengan metode ekstensi di atas. Bisakah Anda melihat lagi?
scobi
@Scott: ini adalah metode yang berguna untuk masalah umum. Namun, saya percaya TReturn elseValue = default(TReturn)hanya tersedia untuk. NET 4.0? Saya memiliki 3,5 SP1 dan saya belum pernah melihat konstruk itu (tidak ada kompiler saya). Saya baru saja memindahkan ini ke dalam metode. Satu masalah, bagaimanapun, adalah bahwa tinju tipe nullable ke objek untuk digunakan dengan metode menghasilkan hasil yang tidak terduga (0 vs nol diharapkan).
Jim Schubert
@ Jim: default(T)kata kunci sudah ada sejak VS2005, tapi saya pikir parameter default adalah fitur .NET 4 baru. Cara termudah untuk itu adalah memiliki dua varian, satu yang menggunakan param dan satu yang tidak. Saya akan memperbarui jawabannya agar kompatibel dengan CLR 2.0. Mengenai tinju - itulah gunanya default. Ini akan menjadi data yang diinisialisasi 0 untuk tipe nilai, dan null untuk semua tipe referensi. TReturn tipe nilai harus tetap tidak dikotak-kotakkan sepanjang fungsi.
scobi
@Scott: Pertanyaan saya adalah tentang parameter default, yang hanya saya lihat dalam bahasa dinamis seperti Ruby. Maksud saya mengenai jenis yang x.Valuedapat dibatalkan adalah bahwa pengembalian harus mengembalikan nol (jika, misalnya, int?adalah nol) atau nilai jika int?memiliki nilai. Kembali 0ketika int? x = nulldilewatkan dan kemas ke objek adalah kasus aneh. Saya telah melihat pemeriksaan serupa untuk jenis nullable di perpustakaan seperti fasih nhibernate dan linfu (saya pikir) untuk kasus khusus ini, memungkinkan Anda untuk menjatuhkan batasan kelas seperti yang disarankan sebelumnya.
Jim Schubert
14

"Tandai jawaban Anda dengan tanda terima untuk memasukkan kode ke proyek Codeplex."

Mengapa? Semua Barang di situs ini di bawah CC-by-sa-2.5 , jadi letakkan saja Extension Project Overflow Anda di bawah lisensi yang sama dan Anda dapat dengan bebas menggunakannya.

Bagaimanapun, ini adalah fungsi String.Reverse, berdasarkan pertanyaan ini .

/// <summary>
/// Reverse a String
/// </summary>
/// <param name="input">The string to Reverse</param>
/// <returns>The reversed String</returns>
public static string Reverse(this string input)
{
    char[] array = input.ToCharArray();
    Array.Reverse(array);
    return new string(array);
}
Michael Stum
sumber
Bukankah String sudah mengimplementasikan IEnumerable <char>? Jadi, Anda hanya perlu mengembalikan String baru (input.Reverse ());
Iain Galloway
Implementasi menggunakan StringBuilder harus lebih cepat.
CodesInChaos
1
@CodeInChaos Pembandingan di stackoverflow.com/questions/228038 mengukur bahwa StringBuilder lebih lambat.
Michael Stum
Kamu benar. Sepertinya persyaratan keamanan thread (mungkin untuk memastikan imutabilitas string yang dikembalikan oleh ToString) memperlambat StringBuilder.
CodesInChaos
2
Semoga Anda tidak menemukan pengganti atau penggabungan karakter.
dalle
14

Saya bosan dengan pemeriksaan nol yang membosankan sambil menarik nilai dari MySqlDataReader, jadi:

public static DateTime? GetNullableDateTime(this MySqlDataReader dr, string fieldName)
{
    DateTime? nullDate = null;
    return dr.IsDBNull(dr.GetOrdinal(fieldName)) ? nullDate : dr.GetDateTime(fieldName);
}

public static string GetNullableString(this MySqlDataReader dr, string fieldName)
{
    return dr.IsDBNull(dr.GetOrdinal(fieldName)) ? String.Empty : dr.GetString(fieldName);
}

public static char? GetNullableChar(this MySqlDataReader dr, string fieldName)
{
    char? nullChar = null;
    return dr.IsDBNull(dr.GetOrdinal(fieldName)) ? nullChar : dr.GetChar(fieldName);
}

Tentu saja ini dapat digunakan dengan SqlDataReader.


Baik hangy dan Joe memiliki beberapa komentar bagus tentang cara melakukan ini, dan sejak itu saya memiliki kesempatan untuk mengimplementasikan sesuatu yang serupa dalam konteks yang berbeda, jadi inilah versi lain:

public static int? GetNullableInt32(this IDataRecord dr, int ordinal)
{
    int? nullInt = null;
    return dr.IsDBNull(ordinal) ? nullInt : dr.GetInt32(ordinal);
}

public static int? GetNullableInt32(this IDataRecord dr, string fieldname)
{
    int ordinal = dr.GetOrdinal(fieldname);
    return dr.GetNullableInt32(ordinal);
}

public static bool? GetNullableBoolean(this IDataRecord dr, int ordinal)
{
    bool? nullBool = null;
    return dr.IsDBNull(ordinal) ? nullBool : dr.GetBoolean(ordinal);
}

public static bool? GetNullableBoolean(this IDataRecord dr, string fieldname)
{
    int ordinal = dr.GetOrdinal(fieldname);
    return dr.GetNullableBoolean(ordinal);
}
Adam Lassek
sumber
2
Ini juga harus berfungsi sebagai metode ekstensi untuk IDataReader.
hangy
2
Sebenarnya, buat parameter "this" dari tipe IDataRecord untuk kompatibilitas maksimum. Dalam versi saya ini, saya memiliki kelebihan yang membutuhkan ordinal, yang panggilan versi fieldName. Menyimpan "GetOrdinal" diikuti oleh pencarian dengan nama.
Joel Mueller
Ada implementasi yang tepat, yang dapat menangani semua jenis nilai: rabdullin.com/journal/2008/12/6/…
Rinat Abdullin
Terima kasih Rinat, saya sudah benar-benar turun ke metode generik tunggal - lihat stackoverflow.com/questions/303287
Adam Lassek
Semua metode ini tampaknya tidak diperlukan karena Anda dapat menggunakan askata kunci untuk mendapatkan nilai dari pembaca yang memungkinkan untuk null. Jika Anda menggabungkan ??operator penggabungan nol dengan operator as, Anda bahkan dapat memiliki nilai default non-nol untuk langsung ke tipe nilai. Lihat stackoverflow.com/questions/746767/…
stevehipwell
14

Itu membuat saya kesal karena LINQ memberi saya OrderBy yang mengambil kelas mengimplementasikan IComparer sebagai argumen, tetapi tidak mendukung lewat dalam fungsi pembanding anonim sederhana. Saya memperbaikinya.

Kelas ini membuat IComparer dari fungsi pembanding Anda ...

/// <summary>
///     Creates an <see cref="IComparer{T}"/> instance for the given
///     delegate function.
/// </summary>
internal class ComparerFactory<T> : IComparer<T>
{
    public static IComparer<T> Create(Func<T, T, int> comparison)
    {
        return new ComparerFactory<T>(comparison);
    }

    private readonly Func<T, T, int> _comparison;

    private ComparerFactory(Func<T, T, int> comparison)
    {
        _comparison = comparison;
    }

    #region IComparer<T> Members

    public int Compare(T x, T y)
    {
        return _comparison(x, y);
    }

    #endregion
}

... dan metode ekstensi ini memaparkan kelebihan OrderBy saya yang baru pada enumerables. Saya ragu ini bekerja untuk LINQ to SQL, tapi itu bagus untuk LINQ to Objects.

public static class EnumerableExtensions
{
    /// <summary>
    /// Sorts the elements of a sequence in ascending order by using a specified comparison delegate.
    /// </summary>
    public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
                                                                     Func<TKey, TKey, int> comparison)
    {
        var comparer = ComparerFactory<TKey>.Create(comparison);
        return source.OrderBy(keySelector, comparer);
    }

    /// <summary>
    /// Sorts the elements of a sequence in descending order by using a specified comparison delegate.
    /// </summary>
    public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
                                                                               Func<TKey, TKey, int> comparison)
    {
        var comparer = ComparerFactory<TKey>.Create(comparison);
        return source.OrderByDescending(keySelector, comparer);
    }
}

Anda dapat menempatkan ini pada codeplex jika Anda mau.

Joel Mueller
sumber
13

Yang ini untuk MVC itu menambahkan kemampuan untuk menghasilkan <label />tag ke Htmlvariabel yang tersedia di setiap ViewPage. Semoga akan bermanfaat bagi orang lain yang mencoba mengembangkan ekstensi serupa.

Menggunakan:

<%= Html.Label("LabelId", "ForId", "Text")%>

Keluaran:

<label id="LabelId" for="ForId">Text</label>

Kode:

public static class HtmlHelperExtensions
{
    public static string Label(this HtmlHelper Html, string @for, string text)
    {
        return Html.Label(null, @for, text);
    }

    public static string Label(this HtmlHelper Html, string @for, string text, object htmlAttributes)
    {
        return Html.Label(null, @for, text, htmlAttributes);
    }

    public static string Label(this HtmlHelper Html, string @for, string text, IDictionary<string, object> htmlAttributes)
    {
        return Html.Label(null, @for, text, htmlAttributes);
    }

    public static string Label(this HtmlHelper Html, string id, string @for, string text)
    {
        return Html.Label(id, @for, text, null);
    }

    public static string Label(this HtmlHelper Html, string id, string @for, string text, object htmlAttributes)
    {
        return Html.Label(id, @for, text, new RouteValueDictionary(htmlAttributes));
    }

    public static string Label(this HtmlHelper Html, string id, string @for, string text, IDictionary<string, object> htmlAttributes)
    {
        TagBuilder tag = new TagBuilder("label");

        tag.MergeAttributes(htmlAttributes);

        if (!string.IsNullOrEmpty(id))
            tag.MergeAttribute("id", Html.AttributeEncode(id));

        tag.MergeAttribute("for", Html.AttributeEncode(@for));

        tag.SetInnerText(Html.Encode(text));

        return tag.ToString(TagRenderMode.Normal);
    }
}
spoon16
sumber
Lihat MvcContrib.FluentHtml
Arnis Lapsa
Ini mungkin harus digandakan dengan Literal sebagai gantinya.
Mark Hurd
12

Putar ini:

DbCommand command = connection.CreateCommand();
command.CommandText = "SELECT @param";

DbParameter param = command.CreateParameter();
param.ParameterName = "@param";
param.Value = "Hello World";

command.Parameters.Add(param);

... dalam hal ini:

DbCommand command = connection.CreateCommand("SELECT {0}", "Hello World");

... menggunakan metode ekstensi ini:

using System;
using System.Data.Common;
using System.Globalization;
using System.Reflection;

namespace DbExtensions {

   public static class Db {

      static readonly Func<DbConnection, DbProviderFactory> getDbProviderFactory;
      static readonly Func<DbCommandBuilder, int, string> getParameterName;
      static readonly Func<DbCommandBuilder, int, string> getParameterPlaceholder;

      static Db() {

         getDbProviderFactory = (Func<DbConnection, DbProviderFactory>)Delegate.CreateDelegate(typeof(Func<DbConnection, DbProviderFactory>), typeof(DbConnection).GetProperty("DbProviderFactory", BindingFlags.Instance | BindingFlags.NonPublic).GetGetMethod(true));
         getParameterName = (Func<DbCommandBuilder, int, string>)Delegate.CreateDelegate(typeof(Func<DbCommandBuilder, int, string>), typeof(DbCommandBuilder).GetMethod("GetParameterName", BindingFlags.Instance | BindingFlags.NonPublic, Type.DefaultBinder, new Type[] { typeof(Int32) }, null));
         getParameterPlaceholder = (Func<DbCommandBuilder, int, string>)Delegate.CreateDelegate(typeof(Func<DbCommandBuilder, int, string>), typeof(DbCommandBuilder).GetMethod("GetParameterPlaceholder", BindingFlags.Instance | BindingFlags.NonPublic, Type.DefaultBinder, new Type[] { typeof(Int32) }, null));
      }

      public static DbProviderFactory GetProviderFactory(this DbConnection connection) {
         return getDbProviderFactory(connection);
      }

      public static DbCommand CreateCommand(this DbConnection connection, string commandText, params object[] parameters) {

         if (connection == null) throw new ArgumentNullException("connection");

         return CreateCommandImpl(GetProviderFactory(connection).CreateCommandBuilder(), connection.CreateCommand(), commandText, parameters);
      }

      private static DbCommand CreateCommandImpl(DbCommandBuilder commandBuilder, DbCommand command, string commandText, params object[] parameters) {

         if (commandBuilder == null) throw new ArgumentNullException("commandBuilder");
         if (command == null) throw new ArgumentNullException("command");
         if (commandText == null) throw new ArgumentNullException("commandText");

         if (parameters == null || parameters.Length == 0) {
            command.CommandText = commandText;
            return command;
         }

         object[] paramPlaceholders = new object[parameters.Length];

         for (int i = 0; i < paramPlaceholders.Length; i++) {

            DbParameter dbParam = command.CreateParameter();
            dbParam.ParameterName = getParameterName(commandBuilder, i);
            dbParam.Value = parameters[i] ?? DBNull.Value;
            command.Parameters.Add(dbParam);

            paramPlaceholders[i] = getParameterPlaceholder(commandBuilder, i);
         }

         command.CommandText = String.Format(CultureInfo.InvariantCulture, commandText, paramPlaceholders);

         return command;
      }
   }
}

Lebih banyak metode ekstensi ADO.NET: DbExtensions

Max Toro
sumber