C # için en sevdiğiniz uzantı yöntemleri nelerdir? (Codeplex.com/extensionoverflow)


478

Mükemmel ve favori uzantı yöntemlerinizi yayınladığınız cevapların bir listesini yapalım .

Gereksinim, tam kodun kaydedilmesi ve bunun bir örneği ve bunun nasıl kullanılacağına ilişkin bir açıklama yapılmasıdır.

Bu konuya yoğun ilgi göstererek Codeplex üzerinde extensionoverflow adlı bir Açık Kaynak Projesi kurdum .

Lütfen kodunuzu Codeplex projesine koymak için cevaplarınızı bir kabulle işaretleyin.

Lütfen bir kaynak kodu değil, tam kaynak kodunu gönderin.

Codeplex Haberleri:

24.08.2010 Codeplex sayfası şimdi burada: http://extensionoverflow.codeplex.com/

11.11.2008 XmlSerialize / XmlDeserialize şimdi Uygulandı ve Birim Test Edildi .

11.11.2008 Hala daha fazla geliştirici için yer var. ;-) ŞİMDİ katılın!

11.11.2008 Üçüncü katılımcı ExtensionOverflow'a katıldı , BKristensen'e hoş geldiniz

11.11.2008 FormatWith şimdi Uygulandı ve Birim Test Edildi .

09.11.2008 İkinci katılımcı ExtensionOverflow'a katıldı . chakrit'e hoşgeldin .

09.11.2008 Daha fazla geliştiriciye ihtiyacımız var. ;-)

09.11.2008 ThrowIfArgumentIsNull in Codeplex'te Uygulandı ve Birim Test Edildi .


Şimdi ilk kod Codeplex sitesine adanmıştır.
bovium

Erik maalesef şimdi her şey kodlamalı olarak başlıyor. Lütfen yine de katılın.
bovium

3
Oldukça iyi görünüyor. Statik sınıfların adlandırılması hakkında bir yorum var. Bunları <tür> Uzantılar olarak adlandırmak çok bilgilendirici değildir. Örneğin, StringExtensions hem biçimlendirme hem de xml öğelerini tutar. Sınıfı neden bu tür genişlettiğinizle adlandırmak daha iyi olduğunu düşünüyorum. Örneğin, UnixDateTimeConversions. Unix zamanına dönüştürme ve Unix zamanına dönüştürme yöntemleri içerdiğini tahmin edebilirsiniz. Sadece bir düşünce!
ecoffey

C # Uzantı Yöntemleri hakkında daha fazla bilgi için bu URL'yi kontrol edin planetofcoders.com/c-extension-methods
Gaurav Agrawal

Yanıtlar:


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

Değiştirmeme izin verir:

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....
}

İle:

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....
}

2
System.Linq kullanıyorsanız derler;
Ryu

11
Belki "EqualsAnyOf", "In" den daha iyi bir isim olabilir?
Tom Bushell

10
Sevdiğimden emin değilim - kısacasını seviyorum In, ama belki IsIndaha iyi olur.
Winston Smith

50
Aynı Contains yöntemini kullanarak: (new [] {1, 2, 3}). (A)
Max Toro içerir

4
Ben de düşündüm In<T>(...)ve standart kütüphane dışında en yararlı uzantısı yöntemi bulundu. Ama isimle çelişiyorum In. Bir yöntem adının ne yaptığını açıkladığı varsayılır, ancak bunu yapmaz In. Ben aradım IsAnyOf<T>(...), ama sanırım IsIn<T>(...)da yeterli olur.
JBSnorro

160

MiscUtil projemde çeşitli uzantı yöntemleri var (tam kaynak orada mevcut - burada tekrar etmeyeceğim). Bazıları diğer sınıfları (aralıklar gibi) içeren favorilerim:

Tarih ve saat bilgileri - çoğunlukla birim testleri için. Onları üretimde kullanacağımdan emin değilim :)

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

Sıradağlar ve adım - Marc Gravell'e operatörünün bunu mümkün kıldığı :

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

Karşılaştırmalar:

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

Bağımsız değişken kontrolü:

x.ThrowIfNull("x");

Anonim türlere (veya uygun özelliklere sahip diğer türlere) uygulanan XML'den LINQ:

// <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()

Push LINQ - burada açıklamak çok uzun sürecek, ancak arayın.


1
Bu iyi! Ben okunabilir :-P olacak söz :-) bazı yamaları gönderebilmesi için Google Code veya Codeplex üzerine çıkarmak gerekir
Chakrit

3
@bovium: Kodu zaten görebilirsiniz. İlk cümlede bağlantıyı takip edin - tam kaynak var.
Jon Skeet

1
@bovium: Bunu kendim yapmayı tercih ederim, bunu code.google.com'a koyup sakıncası yoksa projeyi kendim yönetmeyi tercih ederim. Açıkçası, uygun atıfta bulunursanız Codeplex'e koyma lisansının içindesiniz, ancak çaresiz değilseniz yakında kendim sıralamayı tercih ederim :)
Jon Skeet

1
@Jon Skeet. MIT lisansı altında herkes için ücretsizdir. Ticari veya açık kaynak. Neden güçlerini birleştirip halk için bir uzatma yöntemleri kütüphanesi yapmıyorsunuz?
bovium

1
O kütüphanede bir sürü başka parça ve parça yaptığım için. Projeniz için hepsinin bir kopyasını alabilirsiniz, ancak bir kopyasını da kendi projemde saklamayı tercih ederim.
Jon Skeet

147

dize. Biçim kısayolu:

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

Misal:

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

Hızlı kopyala ve yapıştır için buraya gidin .

Bunun "some string".F("param")yerine yazmak daha doğal değil string.Format("some string", "param")mi?

Daha okunabilir bir ad için aşağıdaki önerilerden birini deneyin:

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

..


11
Kesinlikle kısa - ama ekibinizin yeni üyeleri tarafından okunamayacak.
Jon Skeet

3
Okunabilirliğin, kodunuzun daha büyük düzeninde, hızlı bir şekilde aranabilen / sorulan birkaç kısayol ifadesinden daha önemli olduğunu düşünüyorum.
chakrit

6
Şahsen ben BCL bir kez kalıp ayrıştırabilir ve yeniden kullanabilirsiniz ayrı bir Formatter nesnesi istiyorum. Bu, okunabilirliği ve performansı artıracaktır. BCL ekibine sordum - göreceğiz ...
Jon Skeet

3
Bu bir uzatma yöntemi, tabii ki ekibin yeni üyeleri tarafından okunamayacak. Bu esprili şeylerle ilgili fikir olduğunu düşündüm. Yeni üyeler ne kadar zeki olduğumuzu başka nasıl bilecekler?
MarkJ

17
Tamam ... Ben sadece bu eyleme geçtim ve .With ile - bu yüzden "Bu bir {0}" olsun. ("Test") ile ve çok okunabilir ve mantıklı. FYI
klkitchens

89

Bunların herhangi bir kullanımı var mı?

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

Bu, pythons random.choice (seq) işlevini taklit eder. Güzel.
Daren Thomas

6
Birkaç şey: Herhangi biriniOneOf kabul etmenizi tavsiye ederim . Sonra hep olabilir ayrıca bir alan bir aşırı yüklenme arg ve sadece içine geçer aşırı. Size benzer bir yöntemle ( şu anda en altta aşağı doğru) bir cevap verdim , ancak bir parametre alan bir aşırı yüklenme ile (zamanın% 75'inde bir şey olmasını istersem ne olur?). Ayrıca, sadece bir nit seçim: örnek kodunuz bir başlayacaktır çünkü asla başlatılmaz. IList<T>paramsIList<T>NextBoolCoinTossprobabilityNullReferenceExceptionrand
Dan Tao

3
+1 Bunu gerçekten beğendim, ancak CoinTossuygulanmayı tercih ediyorum rng.NextDouble() < .5çünkü dahili .Next(int)olarak yapıldı, .NextDouble()böylece bir oyuncu kadrosu, bir * ve bir çek kaydedeceksin.
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;
  }
}

Misal:

if (myNumber.Between(3,7))
{
  // ....
}

19
Bunu seviyorum ama sınırları min değerinde kontrol ancak max değeri özel yapmak doğru olup olmadığına karar vermeye çalışıyorum. Bunun kafa karıştırıcı olup olmayacağını merak ediyorum. 5. (5,10) arasında doğrudur ancak 5. (1,5) arasında yanlıştır. İçinde bir yoldaş yöntemi yardımcı olacağını bile emin değilim. Thougts?
Steve Hiner

12
"IsBetween" adı daha anlamlı olmaz mıydı? Ayrıca bir IsBetweenInclusive ve IsBetweenExclusive yapabilirsiniz. Hangisi varsayılan olsa almak için hiçbir fikrim yok.
fretje

2
@Steve: datetime eklentisi olup olmadığı daha anlamlı.
Joel Coehoorn

16
Bana şunu ifade eder: 5. (5,10) arasında false döndürür ve 10 arasında (5,10) arasında false döndürür. Bu bana doğal geliyor.
Alex Baranosky

3
Bana öyle geliyor ki, birden çok insan doğal olanla ilgili farklı fikirlere sahip. Bu nedenle, muhtemelen çok kolay bir hata kaynağı olabileceğinden, ne kullanıldığının açıkça belirtilmesi gerekir (örn. Kapsayıcı ve Özel).
David Miani

58

Uzantı yöntemi:

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

Yöntem tüm türler için geçerlidir ve bir listeye parametre olarak bir dizi öğe eklemenizi sağlar.

Misal:

var list = new List<Int32>();
list.AddRange(5, 4, 8, 4, 2);

15
Bu IList olarak daha iyi olurdu <T>

21
Sadece koleksiyon başlatıcısı kullanın =>var list = new List<int>{5,4,8,4,2};
Arnis Lapsa

Neden sadece <T> .AddRange (IEnumerable <T> koleksiyonu) yönteminiz içinde çağrılmıyor?
Rauhotz

8
@Will: Aslında, kabul etmek en iyisiICollection<T> ; o zaman da, örneğin kullanılan, olabilir LinkedList<T>ve HashSet<T>sadece endeksli koleksiyonları.
Dan Tao

2
Düzenlenen kovaryansını izin pre-.net 4.0
BlueRaja - Dany Pflughoeft

55

Elbette bunu codeplex projesine koyun.

Nesneleri XML olarak serileştirme / serisini kaldırma:

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

8
ToXml()ToString()
İlkini

1
OP'ye kasıtlı olarak bu şekilde yazarsa özür diler, ancak MemoryStreams AND XmlReader / XmlWriter kullanımı aşırı derecede doluydu. StringReader ve StringWriter sınıfı bu işlem için mükemmeldir.
Portman

2
Dikkat, bu threadsafe değildir. Statik diziselleştirici sözlüğüne erişiminizi kesinlikle senkronize etmelisiniz.
Yann Schwartz

2
@Yann, @T, "thread static" özelliğini eklerseniz çok daha kolay. Ardından her iş parçacığı için yeni bir önbellek oluşturulur. Senkronizasyona gerek yok.
Frank Krueger

1
@Jonathan C Dickinson: Burada kullanılan MSDN belgesinde msdn.microsoft.com/en-us/library/… kullanılan yapıcıda (yeni XmlSerializer (tip)) bellek sızıntısı sorunu yok gibi görünüyor. Belki de önbellek koduna gerek yoktur?
slolife

46

IEnumerables için ForEach

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

Naif örnek:

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

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

Harika örnek:

// 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!";
    });

Not:

Bu gibi değil Selectçünkü Select beklediğini sizin işlevi başka bir listeye dönüşürken gelince bir şeyler dönmek için.

ForEach, herhangi bir dönüşüm / veri manipülasyonu olmadan her bir öğe için bir şey yürütmenize izin verir.

Bunu daha işlevsel bir tarzda programlayabildim ve IEnumerable olmasa da List'in ForEach'a sahip olması beni şaşırttı.

Bunu codeplex projesine koy


13
LINQ'nun IEnumerable <T> uzantılarının neden ForEach içermediğine dair mesaj gönderin: stackoverflow.com/questions/317874/…
Neil

13
Yöntemi kullanmadan önce bunu okumanızı tavsiye ederim: blogs.msdn.com/ericlippert/archive/2009/05/18/…
jpbochi

2
@jpbochi: Bu sadece Microsoft demagojisi
abatishchev

1
@abatishchev Ve yorumunuz sadece Microsoft'a karşı önyargı. Eric tarafından yazılan hiçbir kelimeyi geçersiz kılmaz. Birisinin argümanları sadece çalıştığı şirket yüzünden geçerli veya geçersiz kılınmaz.
jpbochi

1
Bu arada, bir noktayı netleştireyim. Bu ForEach uzantı yöntemini kullanmamanız gerektiğini söylemedim. Sadece Eric'in kullanılıp kullanılmayacağına karar vermeden önce maruz kaldığı noktaları dikkate almanız gerektiğini söyledim. Ben okudum ve kullanmamaya karar verdim. Kodunuzla istediğinizi yapmakta özgürsünüz.
jpbochi

43

Yapmanıza izin veren dönüşüm uzantılarım:

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

İşte , TheSoftwareJedi.com'da yayınlandığı gibi

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

Arıza durumunda varsayılan (boş yapıcı veya sayısallar için "0" çağrısı) isteyebilir, "varsayılan" bir değer belirtebilir ("diğer" diyorum) veya null (burada T: sınıfı) isteyebilirsiniz. Hem sessiz istisna modelleri hem de alınan eylemi gösteren bir bool döndüren tipik bir TryParse modeli sağladım ve bir çıkış parametresi yeni değeri tutar. Yani kodumuz böyle şeyler yapabilir

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

Nullable türlerinin her şeye çok temiz bir şekilde girmesini sağlayamadım. Ben havlu atmadan önce yaklaşık 20 dakika denedim.


64
Şahsen ben sonucu belirlemek için denemek / yakalamak yapan bir kod hayranı değilim. Try / catch, amaçlanan mantık IMO dışında meydana gelen hatalar için kullanılmalıdır. hmmmmm
Pure.Krome

Eğer kodu kullanmanızı istemeseydim, bunu göndermezdim! :)
TheSoftwareJedi

Sonunda görünmeyen bir şey. Bunu sevdim. :)
Arnis Lapsa

8
En azından bu "catch" yan tümcesini, ChangeType () öğesinin yalnızca başvuruyu "dönüştüremediğinde" yükselteceği istisnaları yakalamak için değiştirmelisiniz. Ben herhangi bir OutOfMemoryException, ExecutionEngineException, ThreadAbortException veya bir dönüştürme hatası olarak muamele etmek istemiyorum düşünüyorum. Aksi takdirde bu hataları izlemek oldukça zor olacaktır.
Christian.K

2
Ben (yani, başarısız bir dönüşüm ile bir referans türü çağırırsanız , o dönecektir ) ile ToOrNullaynı davranışı olduğuna inanıyorum . Ama daha da önemlisi, benim için bir şey gereksiz görünüyor, çünkü aynı şeyi başarıyor - ama potansiyel olarak bir yakalamak zorunda kalmadan . Bir şey mi kaçırıyorum? ToOrDefaultToOrDefaultnullvar s = myObject as stringvar s = myObject.ToOrNull<string>()InvalidCastException
Dan Tao

43

Özel durumlar günlüğe kaydetme için bir uzantı yöntemi var:

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

Ve bu şekilde kullanılır:

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

[iki kez yayınladığım için üzgünüm; ikincisi daha iyi tasarlanmış :-)]


2
Herkese açık statik geçersiz Günlük (bu İstisna nesnesi) {} okunmalı mı?
Chris S

Bunun BCL veya 3. taraf istisnaları için iyi olduğunu düşünüyorum, ancak kendi istisna türlerinizi alırsanız, temel istisna sınıfınıza günlük kaydı yerleştirebilirsiniz. Bu şekilde Log () 'u çağırmayı hatırlamanız gerekmez.
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);
    }
}

Bir dizeyi Enum'a ayrıştırmak için kullanışlıdır.

public enum TestEnum
{
    Bar,
    Test
}

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

Kredi gidiyor Scott Dorman'a

--- Codeplex projesi için düzenleme ---

Scott Dorman'a kodunu Codeplex projesinde yayınlamamıza izin verip vermeyeceğini sordum. Ondan aldığım cevap bu:

Hem SO postasındaki hem de CodePlex projesindeki başlıklar için teşekkürler. Bu soruya verdiğiniz cevabı iptal ettim. Evet, kod etkin olarak şu anda CodeProject Açık Lisansı ( http://www.codeproject.com/info/cpol10.aspx ) altındaki kamu malıdır .

Bu CodePlex projesinde yer ile hiçbir sorun var ve beni projeye eklemek istiyorsanız (kullanıcı adı sdorman) Ben bu yöntemi artı bazı ek numaralandırma yardımcı yöntemleri ekleyecektir.


Bu numaralandırma ayrıştırma senaryosu her zaman ortaya çıkıyor ... bunu benim
lib'e koymalıyım

Vay be, dizeleri enums ile eşlemek için yöntemler yazıyorum (yeni .NET kullanmaya başladım). Teşekkürler, bu kesinlikle yardımcı olacaktır!
Kevin

4
Nesneden sonra geldiği için bu ToEnum <> () adını da vermeyi düşünebilirsiniz.
Neil

Enum.TryParse <T> 'nin Net 4.0'a eklendiğini unutmayın - blogs.msdn.com/bclteam
Dan Diplo

1
Bu yöntemin Trim kullanması gerektiğini düşünmüyorum. Girişin kırpılması arayanın sorumluluğunda olmalıdır.
CodesInChaos

32

Bunu oldukça faydalı buluyorum:

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

CodePlex üzerinde kullanabilirsiniz.


2
Birisi bunu daha az yetenekli olana açıklayacak kadar nazik olabilir mi?
jpbochi

hahaha Sadece makaleyi okuyun (Joel'in yukarıdaki yorumu) - komik gerçek, ama hemen hemen aynı teknede (alma ucunda, Paula ucunda değil) sadece geri bakıyor! Bir zamanlar bir müteahhit tasarımcısı olduğum / öncü olduğum bir projede çalışmaya başladı - doğrudan kontrolüm altında değildi, ancak takımlarımın çalışma listesinden iş atandı. Patronlar onu parlak olarak övdü (hatta daha sonra bir Dev Lideri olarak işe aldı!). Yazdığı veya tasarladığı her kod parçasının üretime geçmediği ve hepsinin ekibim tarafından baştan tamamen yeniden yazılması gerektiğine hiç şaşmadı!
Wolf5370

31

DateTimeExtensions

Örnekler:

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

5
Aslında "SetTime", aslında mevcut değer ayarlama gibi "WithTime" için yeniden adlandırılmasını öneriyoruz. Aksi halde güzel.
Jon Skeet

28
DateTime.Now.First () - önce ne? Yalnızca örnek koddan anlaşılır.
mackenir

2
Çok hoş. Ancak isimlerin çok daha iyi olabileceğini kabul edin.
bovium

DateTime.Now.First, yöntem iyi belgelenmişse Intellisense'de yeterince açık olacaktır.
Ryan Lundy


28

İşte sunum biçimlendirmesi için sık kullandığım.

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

Whoah, Pokemon istisna işleme ThreadAbortException, vb gibi sorunları gizlemek olacak. Lütfen belirli bir şey yakalamak.
JBRWilkinson

28

İşte Romen rakamları için bir-ve-gelen. Sık kullanılmaz, ancak kullanışlı olabilir. Kullanımı:

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

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

Kaynak:

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

Yani Python Roma Sayısal değişmezleri de değerlendirmeye alınması Nisan Şaka şaka olduğunu Python PEP 313, hatırlatıyor: python.org/dev/peps/pep-0313
torial

25

Boyutlarla başa çıkmanın uygun bir yolu:

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

Bence bu gerçekten kötü kodlama tarzı. Bunun yerine sabit mantık değil sabitler kullanılmalıdır.
xxbbcc

24

Winform Denetimleri için:

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

IsDesignTime Kullanımı:

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

SetDropdownWidth Kullanımı:

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

Bahsetmeyi unuttum, Codeplex'te kullanmaktan çekinmeyin ...


1
Belirtildiği gibi, bu sadece WinForms içindir. WPF ile çalışabilir ancak sorunlar vardır (WPF hakkındaki yorumda msdn.microsoft.com/en-us/library/… adresinde açıklanmıştır ). Bulduğum WPF için en iyi çözüm geekswithblogs.net/lbugnion/archive/2009/09/05/… ' da açıklanmaktadır (ancak statik bir özellik olduğu için, gerçekten bir uzantı yöntemi olarak çalışmaz.)
scobi

23

ThrowIfArgumentIsNull, hepimizin yapması gereken boş denetimi yapmanın güzel bir yoludur.

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

Aşağıda bunu kullanmanın yolu vardır ve ad alanınızdaki tüm sınıflarda veya ad alanını içinde kullandığınız her yerde çalışır.

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

Bu kodu CodePlex projesinde kullanmanız uygundur.


Ben de bunu sevdim, Jon onun içinde var ve ben Umbrella'dan benzer bir şey kullanıyorum, "ArgumentIs" bölümünü bırakmak için durabilirdim.
cfeduke

Evet! Bu da bir kewl uzatma yöntemidir :)
Pure.Krome

3
ArgumentNullException-constructor öğesini yalnızca 1 dize bağımsız değişkeni ile birlikte kullanırsanız, bu bağımsız değişkenin hata iletisi değil, yalnızca parametre adı olması gerekir. Yani kodunuz şöyle görünmelidir: if (obj == null) yeni ArgumentNullException (parametreAdı) atmak;
Tommy Carlier

Bunun default(T)için kullanmak ve sınıf gereksinimini kaldırmak.
Joel Coehoorn

1
@Joel: Yerel türler için varsayılan olmayan değerler, boş değerlerden daha sık geçerli bağımsız değişkenlerdir. Null'a karşı kontrol etmek benim için varsayılana karşı kontrol etmekten daha mantıklı. Tabii ki, sadece Require.ThatArgument(input != null)veya diyerek tüm fikri genelleştiriyorum Require.ThatArgument(personId > 0). Çok daha fazla kod almıyor, çok daha esnek ve iyi okuyor. Hata iletisi veya özel durumun kendisini özelleştirmek istediğinizde işlevler alan ek geçersiz kılmalar var.
StriplingWarrior

22

Visual Basic'ın C # ifadesi ile ifadesini özledim , işte burada:

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

İşte C # ile nasıl kullanacağınız:

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

Yazarken çok tasarruf sağlar!

Bunu şununla karşılaştır:

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

codeplex projesine girmek


4
Sadece bir tahmin, ama T'niz bir yapı ise ne olacağını düşünün.
Rauhotz

5
Ayrıca, aynı sonucu elde etmek için mümkün olan her yerde c # 3.0 özellik başlatıcı sözdizimini kullanın.
Steve

3
@chakrit, işte bir örnek. Yalnızca nesne oluşturulurken geçerlidir Düğme n = yeni Düğme {Name = "Button1", Genişlik = 100, Yükseklik = 20, Etkin = true};
Steve

1
Bu, C # 'ın özellik başlatıcı sözdizimi olayları desteklemediğinden, bağlanmak için çok fazla etkinliğiniz olduğunda kullanışlıdır.
Gabe

1
bu özellik özellik başlatıcıların dışında da kullanışlıdır, çünkü bunları yalnızca yeni bir nesne oluştururken kullanabilirsiniz. bu uzantı önceden oluşturulan nesneler üzerinde çalışabilir.
Brady Moritz

18

Bir camelCaseWord veya PascalCaseWord alır ve "sözcüklendirir", yani camelCaseWord => deve 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])" ) );
}

Sıklıkla Capitalize ile birlikte kullanıyorum

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

Örnek kullanım

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

Codeplex projesinde kullanmak ücretsiz


Capitalize'daki Agrega, performans için oldukça kötüdür, çünkü birçok dize örneği oluşturur. Neden word.Substring (1) kullanmıyorsunuz?
Thomas Levesque

17

Bunu yararlı buldum

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

Arama kodundaki null denetimi kaldırır. Şimdi yapabilirsin

MyList.EmptyIfNull().Where(....)

Evet, birisi "Boş Nesne Deseni" ni unuttuysa, bu yöntem onu ​​düzeltmek için yararlıdır. Koleksiyon asla boş olmamalıdır.
Pavel Hodek

16

Belirtilen kültürü kullanarak biçimlendirilmiş bir dizeyi dize dönüştürün:

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

Misal:

double test = 154.20;
string testString = test.ToCurrency("en-US"); // $154.20

13
Yuvarlama sorunları elde edeceğiniz para birimi için Ondalık'ı kullanmalısınız
Andrew Bullock

Parametrede düz dize yerine bir Enum kullanmaya ne dersiniz
Rulas

15

Aşağıda Rick Strahl'ın kodunu uyarlayan bir uzatma yöntemi var dizeye her dönüştürdüğünüzde bir bayt dizisinin veya metin dosyasının bayt sırası işaretini tahmin etmenizi veya okumanızı durdurmak için (ve yorumları da) .

Snippet şunları yapmanızı sağlar:

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

Herhangi bir hata bulursanız lütfen yorumlara ekleyin. Codeplex projesine dahil etmekten çekinmeyin.

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

Çok yararlı bir yöntem, ama olması gerektiğini düşünmüyorum ve uzatma yöntemi.
Pop Catalin

Bir metin editörü yazıyorsanız, muhtemelen bir uzatma yöntemini garanti eder, ancak çoğu zaman muhtemelen statik özel bir yöntemden başka bir şey olmadığına katılıyorum
Chris S

15

İşte bugün yeni oluşturduğum.

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

Bunu yapmanıza izin verir:

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

daha akıcı ve (IMO) okunması daha kolay:

var lname = (thingy != null ? thingy.Name : null) != null
    ? thingy.Name.ToLower() : null;

1
İstersem Ne thingy.NullOr(t => t.Count), nerede Countbir int? default(TReturn)Boş değil , geri dönmelisiniz, bu şekilde classkısıtlamaya ihtiyacınız olmayacak ve değer türleri için de çalışacaktır
Thomas Levesque

2
TIn'in bir sınıf olması gerekir, aksi takdirde bu genişletme yönteminin hiçbir anlamı yoktur (değer türleri boş olamaz). Ve t.Count örneğiniz yukarıdaki uzantı yöntemiyle çalışır. İkinci bir bakabilir misin?
scobi

@Scott: Bu yaygın bir soruna faydalı bir yöntemdir. Ancak, TReturn elseValue = default(TReturn)sadece .NET 4.0 kullanılabilir inanıyorum ? 3.5 SP1'im var ve bu yapıyı hiç görmedim (derleyicim de yok). Bunu sadece yöntemin içine taşıdım. Bununla birlikte, sorunlardan biri, yöntemle birlikte kullanılmak üzere null olabilecek bir tipin kutulanmasının beklenmedik bir sonuç vermesidir (beklenen değere karşı 0).
Jim Schubert

@Jim: default(T)Anahtar kelime VS2005'ten beri var, ancak varsayılan parametrelerin yeni bir .NET 4 özelliği olduğunu düşünüyorum. Etmenin kolay yolu, biri param alan ve almayan iki varyanta sahip olmak olmalıdır. Cevabı CLR 2.0 uyumlu olacak şekilde güncelleyeceğim. Boks ile ilgili - bu nokta default. Bir değer türü için 0 ile başlatılan veriler ve tüm referans türleri için null olacaktır. TR Değer türünün döndürülmesi, işlev boyunca tamamen kutunun içinde kalmalıdır.
scobi

@Scott: Sorum, yalnızca Ruby gibi dinamik dillerde gördüğüm varsayılan parametre hakkındaydı. Null olabilecek türlerle ilgili noktam x.Value, döndürmenin null (örneğin, int?null olması durumunda) veya bir değeri varsa değer döndürmesi gerektiğidir int?. Dönüş 0sırasında int? x = nullnesnenin geçirilir ve kutu bir tek durumdur. Bu özel durum için akıcı nhibernate ve linfu (sanırım) gibi kütüphanelerde nullable türleri için benzer kontroller gördüm, daha önce önerildiği gibi sınıf kısıtlamasını bırakmanıza izin verdim.
Jim Schubert

14

"Lütfen kodunuzu Codeplex projesine koymak için cevaplarınızı kabul ile işaretleyin."

Neden? Bu sitedeki Tüm Şeyler CC-by-sa-2.5 altında , bu yüzden Uzantı taşma Projenizi aynı lisansa koyun ve özgürce kullanabilirsiniz.

Her neyse, işte bu soruya dayanan bir String.Reverse işlevi .

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

String zaten IEnumerable <char> 'ı uygulamıyor mu? Bu yüzden sadece yeni String (input.Reverse ()) döndürmeniz gerekir;
Iain Galloway

StringBuilder kullanan bir uygulama daha hızlı olmalıdır.
CodesInChaos

1
@CodeInChaos stackoverflow.com/questions/228038'deki Karşılaştırma , StringBuilder'ın daha yavaş olduğunu ölçtü.
Michael Stum

Haklısın. İş parçacığı güvenlik gereksinimleri gibi görünüyor (muhtemelen ToString tarafından döndürülen dizenin değişmezliğini sağlamak için) StringBuilder çok yavaş.
CodesInChaos

2
Umarım suretlerle veya karakterleri birleştirmezsiniz.
dalle

14

MySqlDataReader değerleri çekerken sıkıcı null kontrol bıktınız, bu yüzden:

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

Tabii ki bu herhangi bir SqlDataReader ile kullanılabilir.


Hem hangy hem de Joe, bunun nasıl yapılacağı hakkında bazı iyi yorumlara sahipti ve o zamandan beri farklı bir bağlamda benzer bir şey uygulama fırsatım oldu, bu yüzden başka bir sürüm:

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

2
Bu, IDataReader için bir uzantı yöntemi olarak da çalışmalıdır.
hangy

2
Aslında, maksimum uyumluluk için IDataRecord türündeki "this" parametresini yapın. Bu sürümümde, fieldName sürümünün çağırdığı bir ordinal alan bir aşırı yük var. "GetOrdinal" ve ardından ada göre arama kaydeder.
Joel Mueller

Herhangi bir değer türü ile başa çıkabilecek uygun bir uygulama vardır: rabdullin.com/journal/2008/12/6/…
Rinat

Teşekkürler Rinat, bunu aslında tek bir genel yönteme
indirdim

asAnahtar kelimeyi null değerine izin veren bir okuyucudan değer almak için kullanabileceğinizden, tüm bu yöntemlere gerek yoktur . Null birleştirme ??operatörünü as operatörü ile birleştirirseniz, doğrudan bir değer türüne gitmek için null olmayan bir varsayılan değere bile sahip olabilirsiniz. Bkz. Stackoverflow.com/questions/746767/…
stevehipwell

14

LINQ bana IComparer uygulayan bir sınıfı argüman olarak alan ancak basit bir anonim karşılaştırma işlevinden geçmeyi desteklemeyen bir OrderBy verdi. Bunu düzelttim.

Bu sınıf karşılaştırma işlevinizden bir IComparer oluşturur ...

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

... ve bu genişletme yöntemleri, numaralandırılabilen yeni OrderBy yüklemelerimi ortaya çıkarıyor. Bunun LINQ to SQL için çalıştığından şüpheliyim, ancak LINQ to Objects için harika.

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

İsterseniz bunu codeplex'e koyabilirsiniz.


13

Bu MVC için bir üretme yeteneği ekler <label />Html her değişken kullanılabilir etiketViewPage . Umarım benzer uzantılar geliştirmeye çalışan başkaları için yararlı olacaktır.

kullanın:

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

Çıktı:

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

Kod:

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

MvcContrib.FluentHtml göz atın
Arnis Lapsa

Bu muhtemelen bunun yerine Literal ile çoğaltılmalıdır.
Mark Hurd

12

Bunu çevirin:

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

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

command.Parameters.Add(param);

... bunun içine:

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

... bu uzantı yöntemini kullanarak:

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

Diğer ADO.NET uzantısı yöntemleri: DbExtensions

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.