Phương pháp mở rộng yêu thích của bạn cho C # là gì? (codeplex.com/extensionoverflow)


478

Hãy tạo một danh sách các câu trả lời nơi bạn đăng các phương thức mở rộng tuyệt vời và yêu thích của mình .

Yêu cầu là mã đầy đủ phải được đăng và một ví dụ và giải thích về cách sử dụng nó.

Dựa trên sự quan tâm cao độ trong chủ đề này, tôi đã thiết lập Dự án nguồn mở có tên là phần mở rộng trên Codeplex .

Vui lòng đánh dấu câu trả lời của bạn với sự chấp nhận để đặt mã trong dự án Codeplex.

Xin vui lòng gửi mã nguồn đầy đủ và không phải là một liên kết.

Tin tức Codeplex:

24.08.2010 Trang Codeplex hiện có tại đây: http://extensionoverflow.codeplex.com/

11.11.2008 XmlSerialize / XmlDeserialize hiện được triển khaithử nghiệm đơn vị .

11.11.2008 Vẫn còn chỗ cho nhiều nhà phát triển hơn. ;-) Tham gia NGAY!

11.11.2008 Người đóng góp thứ ba đã tham gia ExtensionOverflow , chào mừng bạn đến với BKristensen

11.11.2008 FormatWith hiện được triển khaithử nghiệm đơn vị .

09.11.2008 Người đóng góp thứ hai đã tham gia ExtensionOverflow . Chào mừng đến với chakrit .

09.11.2008 Chúng tôi cần nhiều nhà phát triển hơn. ;-)

09.11.2008 Ném IfArgumentIsNull ngay bây giờ Đã triển khaiĐơn vị được thử nghiệm trên Codeplex.


Bây giờ mã đầu tiên được cam kết cho trang web Codeplex.
bovium

Erik không may mọi thứ bây giờ được bắt đầu trên codeplex. Hãy tham gia nào.
bovium

3
Trông khá tốt. Tôi có một nhận xét về việc đặt tên các lớp tĩnh. Đặt tên cho chúng <type> Tiện ích mở rộng không có nhiều thông tin. Ví dụ StringExtensions giữ cả định dạng và công cụ xml. Tôi nghĩ tốt hơn nên đặt tên cho lớp với lý do tại sao bạn mở rộng loại đó. Ví dụ: UnixDateTimeConversions. Bạn có thể đoán hợp lý nó giữ các phương thức để chuyển đổi sang và từ thời gian Unix. Chỉ là một ý nghĩ!
ecoffey

Kiểm tra URL này để biết thêm về Phương pháp mở rộng C # Planetofcoders.com/c-extension-methods
Gaurav Agrawal

Câu trả lời:


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

Cho phép tôi thay thế:

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

Với:

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
Nó sẽ biên dịch nếu bạn đang sử dụng System.Linq;
Ryu

11
Có lẽ "EqualsAnyOf" sẽ là một cái tên hay hơn "In"?
Tom Bushell

10
Tôi không chắc là tôi thích nó - tôi thích sự ngắn gọn của nó In, nhưng có lẽ IsInsẽ tốt hơn.
Winston Smith

50
Sử dụng cùng một phương thức Chứa: (mới [] {1, 2, 3}). Chứa (a)
Max Toro

4
Tôi cũng nghĩ In<T>(...)và thấy nó là phương pháp mở rộng hữu ích nhất bên ngoài thư viện chuẩn. Nhưng tôi đang bất hòa với cái tên In. Một tên phương thức được cho là mô tả những gì nó làm, nhưng Inkhông làm như vậy. Tôi đã gọi nó IsAnyOf<T>(...), nhưng tôi đoán IsIn<T>(...)cũng sẽ đầy đủ.
JBSnorro

160

Tôi có nhiều phương thức mở rộng khác nhau trong dự án MiscUtil của mình (nguồn đầy đủ có sẵn ở đó - Tôi sẽ không lặp lại ở đây). Mục ưa thích của tôi, một số trong đó liên quan đến các lớp khác (chẳng hạn như phạm vi):

Ngày và thời gian thứ - chủ yếu cho các bài kiểm tra đơn vị. Không chắc chắn tôi sẽ sử dụng chúng trong sản xuất :)

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

Phạm vi và bước tiến - rất lớn nhờ Marc Gravell cho công cụ điều hành của mình để thực hiện điều này có thể:

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

So sánh:

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

Kiểm tra đối số:

x.ThrowIfNull("x");

LINQ to XML được áp dụng cho các loại ẩn danh (hoặc các loại khác có thuộc tính phù hợp):

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

Đẩy LINQ - sẽ mất quá nhiều thời gian để giải thích ở đây, nhưng hãy tìm kiếm nó.


1
Thật tuyệt! Bạn nên đưa nó lên Google Code hoặc CodePlex để tôi có thể gửi cho bạn một số bản vá :-) Tôi hứa rằng nó sẽ có thể đọc được :-P
chakrit

3
@bovium: Bạn đã có thể xem mã. Theo liên kết trong câu đầu tiên - nguồn đầy đủ là có.
Jon Skeet

1
@bovium: Tôi muốn tự mình làm điều đó, đưa nó vào code.google.com và tự mình quản lý dự án, nếu bạn không phiền. Rõ ràng bạn đang ở trong giấy phép để đưa nó lên Codeplex nếu bạn giữ quyền phân bổ phù hợp, nhưng tôi sẽ sớm tự mình giải quyết nó trừ khi bạn tuyệt vọng :)
Jon Skeet

1
@Jon Skeet. Nó được đặt dưới giấy phép MIT miễn phí sử dụng cho mọi người. Thương mại hoặc nguồn mở. Tại sao không tham gia lực lượng và làm cho một thư viện phương pháp mở rộng cho công chúng.
bovium

1
Chỉ vì tôi làm nhiều bit và phần khác trong thư viện đó. Bạn có thể lấy một bản sao của tất cả cho dự án của bạn, nhưng tôi cũng muốn giữ một bản sao trong dự án của riêng tôi.
Jon Skeet

147

chuỗi. Phím tắt định dạng:

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

Thí dụ:

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

Để sao chép và dán nhanh chóng vào đây .

Bạn không thấy nó tự nhiên hơn để gõ "some string".F("param")thay vì string.Format("some string", "param")?

Để tên dễ đọc hơn , hãy thử một trong những gợi ý sau:

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
Nó chắc chắn ngắn - nhưng sẽ không thể đọc được đối với bất kỳ thành viên mới nào trong nhóm của bạn.
Jon Skeet

3
Tôi nghĩ rằng tính dễ đọc quan trọng hơn trong sơ đồ lớn hơn của mã của bạn hơn là một vài câu lệnh tốc ký có thể nhanh chóng được tra cứu / hỏi.
chakrit

6
Cá nhân tôi muốn một đối tượng Formatter riêng biệt, mà BCL có thể phân tích mẫu của một lần và sử dụng lại. Điều đó sẽ tăng khả năng đọc và hiệu suất. Tôi đã hỏi nhóm BCL - chúng ta sẽ thấy ...
Jon Skeet

3
Đây là một phương pháp mở rộng, tất nhiên nó sẽ không thể đọc được đối với các thành viên mới của nhóm. Tôi nghĩ đó là ý tưởng với những thứ dí dỏm này? Làm thế nào khác các thành viên mới sẽ biết chúng ta thông minh như thế nào?
MarkJ

17
Ok ... Tôi vừa mới thực hiện điều này và thực hiện. Với - vì vậy bạn nhận được "Đây là {0}". Với ("thử nghiệm") và nó rất dễ đọc và có ý nghĩa. FYI
klk bếp

89

Đây có phải là bất kỳ sử dụng?

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

hàm mimicks pythons Random.choice (seq) này. đẹp.
Daren Thomas

6
Vài điều: Tôi khuyên bạn OneOfnên chấp nhận bất kỳ IList<T> . Sau đó, bạn luôn có thể cũng có một tình trạng quá tải mà phải mất một paramsarg và chỉ cần vượt qua đó vào IList<T>tình trạng quá tải. Tôi đã đưa ra một câu trả lời (đi xuống ở phía dưới ngay bây giờ) với một NextBoolphương thức tương tự như của bạn CoinToss, nhưng với sự quá tải cần một probabilitytham số (nếu tôi muốn điều gì đó xảy ra 75% thì sao?). Ngoài ra, chỉ cần chọn nit: mã ví dụ của bạn sẽ ném NullReferenceExceptionrandkhông bao giờ được khởi tạo.
Dan Tao

3
+1 Tôi thực sự thích điều này, nhưng tôi thích CoinTossđược thực hiện hơn rng.NextDouble() < .5vì bên trong .Next(int)được thực hiện .NextDouble()để bạn có thể lưu một diễn viên, * và kiểm tra.
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;
  }
}

Thí dụ:

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

19
Tôi thích cái này nhưng tôi đang cố gắng quyết định xem có đúng không khi kiểm tra giới hạn bao gồm giá trị tối thiểu nhưng độc quyền trên giá trị tối đa. Tôi tự hỏi nếu điều đó sẽ gây nhầm lẫn. 5. Giữa (5,10) là đúng nhưng 5. Giữa (1,5) là sai. Thậm chí không chắc chắn rằng một người bạn đồng hành trong phương pháp sẽ giúp. Thằn lằn?
Steve Hiner

12
Cái tên "IsB between" có ý nghĩa hơn không? Cũng có thể tạo một IsB AmongIninating và IsB AmongExinating. Không có ý tưởng nào để mặc định mặc dù.
Fretje

2
@Steve: sẽ có ý nghĩa hơn nếu đó là một phần mở rộng datetime.
Joel Coehoorn

16
Đối với tôi giữa ngụ ý: 5.B between (5,10) trả về false và 10.B between (5,10) cũng trả về false. Điều đó chỉ cảm thấy tự nhiên với tôi.
Alex Baranosky

3
Dường như với tôi, nhiều người có những ý tưởng khác nhau về những gì là tự nhiên. Do đó, có lẽ nên nói rõ ràng những gì đang được sử dụng (nghĩa là Bao gồm so với độc quyền), vì đây có thể là một nguồn lỗi rất dễ dàng.
David Miani

58

Phương pháp mở rộng:

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

Phương pháp áp dụng cho tất cả các loại và cho phép bạn thêm một loạt các mục vào danh sách dưới dạng tham số.

Thí dụ:

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

15
Sẽ tốt hơn khi IList này <T>

21
Chỉ cần sử dụng bộ khởi tạo bộ sưu tập =>var list = new List<int>{5,4,8,4,2};
Arnis Lapsa

Tại sao không chỉ gọi Danh sách <T> .AddRange (bộ sưu tập <T> IEnumerable) trong phương thức của bạn?
Rauhotz

8
@ Will: Trên thực tế, tốt nhất là chấp nhận một ICollection<T>; sau đó, nó cũng có thể được sử dụng, ví dụ, LinkedList<T>HashSet<T>, không chỉ các bộ sưu tập được lập chỉ mục.
Dan Tao

2
Đã chỉnh sửa để cho phép hiệp phương sai trong pre-.net 4.0
BlueRaja - Danny Pflughoeft

55

Bằng mọi cách đặt điều này trong dự án codeplex.

Các đối tượng tuần tự hóa / giải tuần tự hóa thành 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.
    }
}

8
Tôi muốn gọi người đầu tiên ToXml()(như ToString())
Jay Bazuzi

1
Xin lỗi OP nếu anh ta cố tình viết nó theo cách này, nhưng việc sử dụng MemoryStreams AND XmlReader / XmlWriter là quá mức cần thiết. Lớp StringReader và StringWriter là hoàn hảo cho hoạt động này.
Portman

2
Hãy coi chừng, đây không phải là chủ đề an toàn. Bạn chắc chắn nên đồng bộ hóa quyền truy cập của mình vào từ điển serialisers tĩnh.
Yann Schwartz

2
@Yann, @T, Sẽ dễ dàng hơn nhiều nếu bạn chỉ cần thêm thuộc tính "thread static". Sau đó, một bộ đệm mới sẽ được tạo cho mỗi luồng. Không cần đồng bộ hóa.
Frank Krueger

1
@Jonathan C Dickinson: Nó xuất hiện từ các tài liệu MSDN ở đây msdn.microsoft.com/en-us/l Library / . Vì vậy, có thể mã bộ nhớ đệm là không cần thiết?
slolife

46

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

Ví dụ ngây thơ:

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

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

Ví dụ tuyệt vời:

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

Ghi chú:

Điều này là không thích Selectbởi vì Select hy vọng chức năng của bạn sẽ trả về một cái gì đó như để chuyển đổi sang một danh sách khác.

ForEach chỉ đơn giản cho phép bạn thực thi một cái gì đó cho mỗi mục mà không có bất kỳ biến đổi / thao tác dữ liệu nào.

Tôi đã thực hiện điều này để tôi có thể lập trình theo phong cách chức năng hơn và tôi đã ngạc nhiên khi Danh sách có ForEach trong khi IEnumerable thì không.

Đặt điều này trong dự án codeplex


13
Đăng về lý do tại sao các tiện ích mở rộng <T> IEn của IEQ không bao gồm ForEach: stackoverflow.com/questions/317874/ mẹo
Neil

13
Tôi khuyên bạn nên đọc bài viết này trước khi sử dụng phương pháp: blogs.msdn.com/ericlippert/archive/2009/05/18/...
jpbochi

2
@jpbochi: Đây chỉ là Microsoft mị dân
abatishchev

1
@abatishchev Và nhận xét của bạn chỉ là định kiến ​​đối với Microsoft. Nó không làm mất hiệu lực bất kỳ từ nào được viết bởi Eric. Lập luận của ai đó không có giá trị hoặc không hợp lệ chỉ vì công ty mà anh ấy / cô ấy làm việc.
jpbochi

1
Nhân tiện, hãy để tôi làm cho một điểm rõ ràng. Tôi không nói rằng bạn không nên sử dụng phương pháp mở rộng ForEach này. Tôi chỉ nói rằng bạn nên xem xét những điểm mà Eric tiếp xúc trước khi bạn quyết định có nên sử dụng nó hay không. Tôi đọc nó và tôi quyết định không sử dụng nó. Bạn có thể tự do làm bất cứ điều gì bạn muốn với mã của bạn.
jpbochi

43

Tiện ích mở rộng chuyển đổi của tôi cho phép bạn thực hiện:

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

Đây là, như được đăng trên 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;
    }
}

Bạn có thể yêu cầu mặc định (gọi hàm tạo trống hoặc "0" cho số) khi không thành công, chỉ định giá trị "mặc định" (tôi gọi nó là "khác") hoặc yêu cầu null (trong đó lớp T:). Tôi cũng đã cung cấp cả các mô hình ngoại lệ im lặng và một mô hình TryPude điển hình trả về một bool chỉ ra hành động được thực hiện và một tham số ngoài giữ giá trị mới. Vì vậy, mã của chúng tôi có thể làm những việc như thế này

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

Tôi không thể có được các loại Nullable để cuộn vào toàn bộ mọi thứ rất sạch sẽ. Tôi đã thử trong khoảng 20 phút trước khi ném vào khăn.


64
Cá nhân, tôi không phải là người hâm mộ mã thử / bắt để xác định kết quả. Thử / bắt nên được sử dụng cho các lỗi xảy ra bên ngoài logic dự định, IMO. hmmmmm
Pure.Krom

Nếu tôi không muốn bạn sử dụng mã, tôi sẽ không đăng nó! :)
TheSoftwareJedi

Cuối cùng là một cái gì đó không nhìn thấy. Tôi thích nó. :)
Arnis Lapsa

8
Ít nhất bạn nên thay đổi mệnh đề "bắt" đó để chỉ bắt những ngoại lệ mà ChangeType () sẽ nêu ra khi nó không thể "chuyển đổi" tham chiếu. Tôi nghĩ rằng bạn sẽ không muốn có bất kỳ OutOfMemoryException, ExecutEngineException, ThreadAbortException hoặc tương tự bị coi là một lỗi chuyển đổi. Những thứ đó sẽ khá khó để theo dõi lỗi.
Christian.K

2
Tôi tin rằng ToOrNullcó hành vi chính xác giống như ToOrDefault(nghĩa là, nếu bạn gọi ToOrDefaultmột loại tham chiếu với một chuyển đổi không thành công, nó sẽ trả về null). Nhưng quan trọng hơn, nó có vẻ hơi dư thừa đối với tôi vì var s = myObject as stringhoàn thành điều tương tự var s = myObject.ToOrNull<string>()- nhưng không có khả năng phải bắt một InvalidCastException. Tui bỏ lỡ điều gì vậy?
Dan Tao

43

Tôi có một phương pháp mở rộng để ghi lại các ngoại lệ:

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

Và nó được sử dụng như thế này:

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

[xin lỗi vì đã đăng hai lần; cái thứ 2 được thiết kế tốt hơn :-)]


2
Có nên đọc Nhật ký khoảng trống tĩnh (ngoại lệ obj) {} này không?
Chris S

Tôi nghĩ rằng điều này tốt cho ngoại lệ của BCL hoặc bên thứ 3, nhưng nếu bạn cuộn các loại ngoại lệ của riêng mình, bạn có thể đặt đăng nhập vào lớp ngoại lệ cơ sở của mình. Bằng cách đó, bạn không phải nhớ gọi 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);
    }
}

Hữu ích để phân tích một chuỗi thành một Enum.

public enum TestEnum
{
    Bar,
    Test
}

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

Tín dụng cho Scott Dorman

--- Chỉnh sửa cho dự án Codeplex ---

Tôi đã hỏi Scott Dorman rằng anh ấy có phiền chúng tôi xuất bản mã của anh ấy trong dự án Codeplex không. Đây là câu trả lời tôi nhận được từ anh ấy:

Cảm ơn bạn đã ủng hộ cả bài SO và dự án CodePlex. Tôi đã nâng cao câu trả lời của bạn cho câu hỏi. Có, mã này có hiệu quả trong phạm vi công cộng hiện tại theo Giấy phép mở CodeProject ( http://www.codeproject.com/info/cpol10.aspx ).

Tôi không có vấn đề gì với việc này được bao gồm trong dự án CodePlex và nếu bạn muốn thêm tôi vào dự án (tên người dùng là sdorman) tôi sẽ thêm phương thức đó cộng với một số phương thức trợ giúp enum bổ sung.


Kịch bản phân tích cú pháp này xuất hiện mọi lúc ... phải đưa nó vào lib của tôi :-)
chakrit

Ồ, tôi đã viết các phương thức để ánh xạ các chuỗi thành enum (mới bắt đầu sử dụng .NET). Cảm ơn, điều này sẽ hoàn toàn giúp đỡ!
Kevin

4
Bạn cũng có thể xem xét việc đặt tên ToEnum <> () này, vì nó xuất hiện sau đối tượng.
Neil

Lưu ý rằng Enum.TryPude <T> đã được thêm vào Net 4.0 - blog.msdn.com/bclteam
Dan Diplo

1
Tôi không nghĩ phương pháp này nên sử dụng Trim. Cắt tỉa đầu vào phải là trách nhiệm của người gọi.
CodeInChaos

32

Tôi thấy cái này khá hữu ích:

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

Bạn có thể sử dụng nó trên CodePlex.


2
Ai đó có thể tử tế để giải thích nó cho những người kém năng khiếu của chúng ta không?
jpbochi

hahaha Chỉ cần đọc bài viết (bình luận của Joel ở trên) - thật buồn cười, nhưng đã ở trên cùng một chiếc thuyền (ở đầu nhận, không phải là kết thúc Paula) thật buồn cười khi nhìn lại! Một lần có một nhà thầu được đưa vào để làm việc trong một dự án mà tôi là người chỉ định / nhà phát triển chính - cô ấy không thuộc quyền kiểm soát trực tiếp của tôi, nhưng được giao công việc từ danh sách công việc của nhóm tôi. Các ông chủ ca ngợi cô là người thông minh (thậm chí còn thuê cô sau đó làm Dev Dev!). Họ không bao giờ nhận ra rằng mọi đoạn mã cô ấy viết hoặc thiết kế đều không được đưa vào sản xuất và tất cả phải được viết lại hoàn toàn từ đầu bởi đội của tôi!
Wolf5370

31

DateTimeExtensions

Ví dụ:

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
Tôi khuyên bạn nên đổi tên "SetTime" thành "WithTime" vì nó không thực sự đặt nó trong giá trị hiện có. Mặc dù tốt đẹp.
Jon Skeet

28
DateTime.Now.First () - đầu tiên là gì? Nó chỉ rõ ràng từ mã mẫu.
mackenir

2
Rất đẹp. Nhưng đồng ý rằng tên có thể tốt hơn rất nhiều.
bovium

DateTime.Now.First sẽ đủ rõ ràng trong Intellisense nếu phương thức được ghi chép tốt.
Ryan Lundy

29

gitorious.org/cadenza là một thư viện đầy đủ của một số phương pháp mở rộng hữu ích nhất mà tôi đã thấy.


12 phương pháp mở rộng khá cơ bản. Tôi hơi bị choáng ngợp bởi những tảng đá đơn sắc.
mackenir

(Tôi đang nói về phiên bản đã phát hành, không phải phiên bản bạn cần sử dụng kiểm soát nguồn để có được)
mackenir

28

Đây là một cái tôi sử dụng thường xuyên để định dạng trình bày.

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, việc xử lý ngoại lệ của Pokemon sẽ che giấu các vấn đề như ThreadAdortException, v.v. Vui lòng nắm bắt điều gì đó cụ thể.
JBRWilkinson

28

Đây là một và từ cho các chữ số La Mã. Không thường xuyên được sử dụng, nhưng có thể có ích. Sử dụng:

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

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

Nguồn:

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

Điều đó làm tôi nhớ đến Python PEP 313, đó là một trò đùa Cá tháng Tư để bao gồm các chữ số La Mã trong python: python.org/dev/peps/pep-0313
torial

25

Một cách thuận tiện để đối phó với kích thước:

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

Theo tôi đây là phong cách mã hóa thực sự kém. Hằng số nên được sử dụng thay thế, không logic logic.
xxbbcc

24

Đối với điều khiển 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));
}

Cách sử dụng 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
    }
}

Cách sử dụng 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();

Tôi quên đề cập đến, cứ thoải mái sử dụng những thứ này trên Codeplex ...


1
Như đã đề cập, cái này chỉ dành cho WinForms. Nó có thể hoạt động với WPF nhưng có một số vấn đề (được mô tả trong nhận xét về WPF tại msdn.microsoft.com/en-us/l Library / trộm ). Giải pháp tốt nhất cho WPF mà tôi đã tìm thấy được mô tả trong geekswithbloss.net/lormsnion/archive/2009/09/05/ (mặc dù, vì nó là một thuộc tính tĩnh, nhưng nó không thực sự hoạt động như một phương thức mở rộng.)
scobi

23

Throw IfArgumentIsNull là một cách hay để kiểm tra null mà tất cả chúng ta nên làm.

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

Dưới đây là cách sử dụng nó và nó hoạt động trên tất cả các lớp trong không gian tên của bạn hoặc bất cứ nơi nào bạn sử dụng không gian tên bên trong nó.

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

Bạn có thể sử dụng mã này trong dự án CodePlex .


Tôi cũng thích điều này, Jon có nó trong anh ấy, và tôi sử dụng một cái gì đó tương tự từ Umbrella, có thể đứng để thả phần "ArgumentIs".
cfeduke

Vâng! đây cũng là một phương thức mở rộng kewl :)
Pure.Krom

3
Nếu bạn sử dụng hàm tạo ArgumentNullException chỉ có 1 đối số chuỗi, thì đối số đó phải chỉ là tên tham số chứ không phải thông báo lỗi. Vì vậy, mã của bạn sẽ trông như thế này: if (obj == null) ném mới ArgumentNullException (tham sốName);
Tommy Carlier

Tôi sẽ sử dụng default(T)cho điều này và loại bỏ yêu cầu lớp học.
Joel Coehoorn

1
@Joel: Các giá trị không mặc định cho các kiểu gốc là các đối số hợp pháp thường xuyên hơn các giá trị null. Kiểm tra chống lại null có ý nghĩa với tôi hơn là kiểm tra chống lại mặc định. Tất nhiên, tôi chỉ khái quát toàn bộ ý tưởng bằng cách nói Require.ThatArgument(input != null)hay Require.ThatArgument(personId > 0). Nó không lấy nhiều mã hơn, nó linh hoạt hơn rất nhiều và nó đọc rất hay. Tôi có các phần ghi đè bổ sung mất chức năng khi bạn muốn tùy chỉnh thông báo lỗi hoặc chính ngoại lệ.
StriplingWar Warrior

22

Tôi nhớ câu lệnh With của Visual Basic khi chuyển sang C #, vì vậy nó sẽ xuất hiện:

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

Và đây là cách sử dụng nó trong C #:

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

Tiết kiệm rất nhiều gõ!

So sánh điều này với:

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

đưa vào dự án codeplex


4
Chỉ là một phỏng đoán, nhưng hãy nghĩ về những gì sẽ xảy ra nếu T của bạn là một cấu trúc.
Rauhotz

5
Tôi cũng sử dụng cú pháp khởi tạo thuộc tính c # 3.0 bất cứ khi nào có thể để đạt được kết quả tương tự.
Steve

3
@chakrit, đây là một ví dụ. Nó chỉ áp dụng khi tạo đối tượng Nút n = new Nút {Name = "Nút1", Width = 100, height = 20, Enables = true};
Steve

1
Điều này sẽ hữu ích khi bạn có nhiều sự kiện để kết nối, vì cú pháp khởi tạo thuộc tính của C # không hỗ trợ các sự kiện.
Gabe

1
đây cũng là người dùng bên ngoài các công cụ khởi tạo thuộc tính, bởi vì bạn chỉ có thể sử dụng chúng khi tạo một đối tượng mới. phần mở rộng này có thể hoạt động trên các đối tượng được tạo trước đó.
Brady Moritz

18

Lấy một con lạc đàCaseWord hoặc PascalCaseWord và "diễn đạt" nó, tức là camelCaseWord => lạc đà 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])" ) );
}

Tôi thường sử dụng nó trong kết hợp với Capitalize

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

Ví dụ sử dụng

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

Miễn phí sử dụng trong dự án codeplex


Tổng hợp trong Capitalize khá tệ cho hiệu năng, vì nó tạo ra nhiều trường hợp chuỗi. Tại sao không sử dụng word.Sub chuỗi (1) thay thế?
Thomas Levesque

17

Tôi thấy cái này hữu ích

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

Nó loại bỏ kiểm tra null trong mã gọi. Bây giờ bạn có thể làm

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

Có, nếu ai đó quên "Mẫu đối tượng Null" thì phương pháp này rất hữu ích để vá nó. Bộ sưu tập không bao giờ nên là null.
Pavel Hodek

16

Chuyển đổi một chuỗi thành chuỗi được định dạng bằng văn hóa đã chỉ định:

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

Thí dụ:

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

13
Bạn nên sử dụng Thập phân cho các loại tiền tệ khác, bạn sẽ gặp các vấn đề làm tròn
Andrew Bullock

Điều gì về việc sử dụng Enum trong tham số thay vì chuỗi đơn giản
Công thức

15

Dưới đây là một phương pháp mở rộng điều chỉnh mã của Rick Strahl (và cả các nhận xét) để ngăn bạn phải đoán hoặc đọc dấu thứ tự byte của một mảng byte hoặc tệp văn bản mỗi khi bạn chuyển đổi nó thành một chuỗi.

Đoạn mã cho phép bạn chỉ cần làm:

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

Nếu bạn tìm thấy bất kỳ lỗi xin vui lòng thêm vào các ý kiến. Hãy đưa nó vào dự án 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();
            }
        }
    }
}

Phương pháp rất hữu ích, nhưng tôi không nghĩ nó nên và phương pháp mở rộng.
Pop Catalin

Nếu bạn đang viết một trình soạn thảo văn bản, nó có thể đảm bảo một phương thức mở rộng, nhưng tôi đồng ý hầu hết thời gian có lẽ không hơn gì một phương thức riêng tư tĩnh
Chris S

15

Đây là một cái tôi vừa tạo hôm nay.

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

Nó cho phép bạn làm điều này:

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

thông thạo hơn và (IMO) dễ đọc hơn thế này:

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

1
Nếu tôi muốn thingy.NullOr(t => t.Count), Countint ở đâu? Bạn nên trả về default(TReturn)chứ không phải null, theo cách đó bạn sẽ không cần classràng buộc và nó cũng sẽ hoạt động với các loại giá trị
Thomas Levesque

2
TIn phải được yêu cầu là một lớp, nếu không thì toàn bộ phương thức mở rộng này không có ý nghĩa (các loại giá trị không thể là null). Và ví dụ của bạn với t.Count không hoạt động với phương thức mở rộng ở trên. Bạn có thể có một cái nhìn thứ hai?
scobi

@Scott: đây là một phương pháp hữu ích cho một vấn đề phổ biến. Tuy nhiên, tôi tin rằng TReturn elseValue = default(TReturn)chỉ có sẵn cho .NET 4.0? Tôi có 3.5 SP1 và tôi chưa bao giờ thấy cấu trúc đó (cũng không có trình biên dịch của tôi). Tôi chỉ di chuyển này vào bên trong phương thức. Tuy nhiên, có một vấn đề là đấm bốc một loại không thể đối tượng để sử dụng với phương thức mang lại kết quả không mong muốn (0 so với null dự kiến).
Jim Schubert

@Jim: default(T)từ khóa đã có từ thời VS2005, nhưng tôi nghĩ các tham số mặc định là một tính năng .NET 4 mới. Cách dễ dàng xung quanh nó là có hai biến thể, một biến thể lấy param và một biến thể không. Tôi sẽ cập nhật câu trả lời để tương thích CLR 2.0. Về quyền anh - đó là điểm chính của default. Nó sẽ là dữ liệu khởi tạo 0 cho một loại giá trị và null cho tất cả các loại tham chiếu. Một TReturn của một loại giá trị sẽ vẫn không được mở hộp trong suốt quá trình thông qua chức năng.
scobi

@Scott: Câu hỏi của tôi là về tham số mặc định, điều mà tôi chỉ thấy trong các ngôn ngữ động như Ruby. Quan điểm của tôi về các loại nullable là việc trả về x.Valuesẽ trả về null (ví dụ: nếu int?là null) hoặc giá trị nếu int?có giá trị. Trở lại 0khi int? x = nullđược thông qua và đóng hộp vào đối tượng là một trường hợp kỳ lạ. Tôi đã thấy các kiểm tra tương tự đối với các loại không có giá trị trong các thư viện như thông thạo nhibernate và linfu (tôi nghĩ) cho trường hợp cụ thể này, cho phép bạn loại bỏ ràng buộc lớp như đề xuất trước đây.
Jim Schubert

14

"Vui lòng đánh dấu câu trả lời của bạn với sự chấp nhận để đặt mã vào dự án Codeplex."

Tại sao? Tất cả nội dung trên trang web này theo CC-by-sa-2.5 , vì vậy chỉ cần đặt Dự án tràn tiện ích mở rộng của bạn theo cùng một giấy phép và bạn có thể tự do sử dụng nó.

Dù sao, đây là một hàm String.Reverse, dựa trên câu hỏi này .

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

Không phải String đã triển khai IEnumerable <char>? Vì vậy, bạn chỉ cần trả về Chuỗi mới (input.Reverse ());
Iain Galloway

Việc triển khai bằng StringBuilder sẽ nhanh hơn.
CodeInChaos

1
@CodeInChaos Điểm chuẩn trong stackoverflow.com/questions/228038 đo được rằng StringBuilder chậm hơn.
Michael Stum

Bạn đúng. Có vẻ như các yêu cầu an toàn của luồng (có thể để đảm bảo tính bất biến của chuỗi được trả về bởi ToString) làm chậm StringBuilder xuống rất nhiều.
CodeInChaos

2
Hy vọng bạn không gặp phải bất kỳ người thay thế hoặc kết hợp các nhân vật.
dalle

14

Tôi cảm thấy mệt mỏi với việc kiểm tra null tẻ nhạt trong khi lấy các giá trị từ MySqlDataReader, vì vậy:

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

Tất nhiên điều này có thể được sử dụng với bất kỳ SqlDataReader.


Cả hangy và Joe đều có một số nhận xét tốt về cách thực hiện điều này và từ đó tôi đã có cơ hội thực hiện một cái gì đó tương tự trong một bối cảnh khác, vì vậy đây là một phiên bản khác:

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
Điều này cũng sẽ hoạt động như một phương thức mở rộng cho IDataReader.
nôn nao

2
Trên thực tế, tạo tham số "này" của loại IDataRecord để tương thích tối đa. Trong phiên bản này, tôi có một tình trạng quá tải cần một quy tắc, mà phiên bản fieldName gọi. Lưu "GetOrdinal" theo sau là tra cứu theo tên.
Joel Mueller

Có một cách thực hiện đúng, có thể xử lý bất kỳ loại giá trị nào: rabdullin.com/journal 2008/12/6 / Đổi
Rinat Abdullin

Cảm ơn Rinat, tôi thực sự đã hiểu được điều này theo một phương pháp chung duy nhất - xem stackoverflow.com/questions/303287
Adam Lassek

Tất cả các phương thức này dường như là không cần thiết vì bạn có thể sử dụng astừ khóa để nhận giá trị từ trình đọc cho phép null. Nếu bạn kết hợp ??toán tử hợp nhất null với toán tử as, bạn thậm chí có thể có giá trị mặc định không null để chuyển trực tiếp đến loại giá trị. Xem stackoverflow.com/questions/746767/
Mạnh

14

Điều đó làm tôi bực mình khi LINQ đưa cho tôi một OrderBy lấy một lớp triển khai IComparer làm đối số, nhưng không hỗ trợ chuyển vào một hàm so sánh ẩn danh đơn giản. Tôi đã khắc phục điều đó.

Lớp này tạo ra một IComparer từ chức năng so sánh của bạn ...

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

... và các phương thức mở rộng này cho thấy tình trạng quá tải OrderBy mới của tôi trên bảng liệt kê. Tôi nghi ngờ điều này hoạt động với LINQ to SQL, nhưng thật tuyệt vời cho LINQ to Object.

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

Bạn có thể đặt nó trên codeplex nếu bạn thích.


13

Cái này là dành cho MVC, nó bổ sung khả năng tạo <label /> thẻ cho Htmlbiến có sẵn trong mỗi ViewPage. Hy vọng nó sẽ được sử dụng cho những người khác đang cố gắng phát triển các tiện ích mở rộng tương tự.

Sử dụng:

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

Đầu ra:

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

Mã số:

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

Kiểm tra MvcContrib.FluentHtml
Arnis Lapsa

Điều này có lẽ nên được nhân đôi với chữ.
Đánh dấu Hurd

12

Biến điều này:

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

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

command.Parameters.Add(param);

... vào đây:

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

... sử dụng phương thức mở rộng này:

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

Các phương thức mở rộng ADO.NET khác: DbExtensions

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.