让我们列出你发布优秀和最喜欢的扩展方法的答案.
要求是必须发布完整代码并提供示例和如何使用它的说明.
基于对该主题的高度关注,我在Codeplex上设置了一个名为extensionoverflow的开源项目.
请标记您的答案并接受将代码放入Codeplex项目中.
请发布完整的源代码而不是链接.
Codeplex新闻:
24.08.2010 Codeplex页面现在在这里:http://extensionoverflow.codeplex.com/
11.11.2008 XmlSerialize/XmlDeserialize现在已实现并且已经过单元测试.
11.11.2008仍有更多开发人员的空间.;-) 现在加入!
11.11.2008第三个贡献者加入了ExtensionOverflow,欢迎来到BKristensen
11.11.2008 FormatWith现在已实现且已经过单元测试.
09.11.2008第二个贡献者加入了ExtensionOverflow.欢迎来到chakrit.
09.11.2008我们需要更多开发人员.;-)
09.11.2008 ThrowIfArgumentIsNull现在已在Codeplex上实现和单元测试.
public static bool In(this T source, params T[] list) { if(null==source) throw new ArgumentNullException("source"); return list.Contains(source); }
允许我替换:
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.... }
附:
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.... }
我在MiscUtil项目中有各种扩展方法(那里有完整的源代码 - 我不打算在这里重复它).我最喜欢的,其中一些涉及其他类(如范围):
日期和时间 - 主要用于单元测试.不确定我是否会在生产中使用它们:)
var birthday = 19.June(1976); var workingDay = 7.Hours() + 30.Minutes();
范围和踩踏 - 非常感谢Marc Gravell为他的操作员提供的服务:
var evenNaturals = 2.To(int.MaxValue).Step(2); var daysSinceBirth = birthday.To(DateTime.Today).Step(1.Days());
比较:
var myComparer = ProjectionComparer.Create(Person p => p.Name); var next = myComparer.ThenBy(p => p.Age); var reversed = myComparer.Reverse();
参数检查:
x.ThrowIfNull("x");
LINQ to XML应用于匿名类型(或具有适当属性的其他类型):
//Jon 32 new { Name="Jon", Age=32}.ToXElements(); // Name="Jon" Age="32" (as XAttributes, obviously) new { Name="Jon", Age=32}.ToXAttributes()
推LINQ - 在这里解释需要很长时间,但要搜索它.
string.Format快捷方式:
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); } }
例:
var s = "The co-ordinate is ({0}, {1})".F(point.X, point.Y);
要快速复制粘贴,请转到此处.
你不觉得打字更自然吗? "some string".F("param")
而不是string.Format("some string", "param")
?
更多 易读的名称,请尝试以下建议之一:
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");
..
这些有用吗?
public static bool CoinToss(this Random rng) { return rng.Next(2) == 0; } public static T OneOf(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!");
public static class ComparableExtensions { public static bool Between(this T actual, T lower, T upper) where T : IComparable { return actual.CompareTo(lower) >= 0 && actual.CompareTo(upper) < 0; } }
例:
if (myNumber.Between(3,7)) { // .... }
扩展方法:
public static void AddRange(this ICollection list, params S[] values) where S : T { foreach (S value in values) list.Add(value); }
该方法适用于所有类型,并允许您将一系列项目作为参数添加到列表中.
例:
var list = new List(); list.AddRange(5, 4, 8, 4, 2);
一定要把它放在codeplex项目中.
将对象序列化/反序列化为XML:
///Serializes an object of type T in to an xml string ///Any class type /// Object to serialize ///A string that represents Xml, empty otherwise public static string XmlSerialize(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(); } } /// Deserializes an xml string in to an object of Type T ///Any class type /// Xml as string to deserialize from ///A new object of type T is successful, null if failed public static T XmlDeserialize(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. } }
ForEach for IEnumerables
public static class FrameworkExtensions { // a map function public static void ForEach(this IEnumerable @enum, Action mapFunction) { foreach (var item in @enum) mapFunction(item); } }
天真的例子:
var buttons = GetListOfButtons() as IEnumerable
很酷的例子:
// 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!"; });
注意:
这不是Select
因为Select
期望你的函数返回一些东西,就像转换到另一个列表一样.
ForEach只允许您为每个项执行某些操作而无需任何转换/数据操作.
我做了这个,所以我可以用更实用的风格编程,我很惊讶List有一个ForEach而IEnumerable没有.
把它放在codeplex项目中
我的转换扩展程序允许您执行以下操作:
int i = myString.To();
这是,在TheSoftwareJedi.com张贴
public static T To(this IConvertible obj) { return (T)Convert.ChangeType(obj, typeof(T)); } public static T ToOrDefault (this IConvertible obj) { try { return To (obj); } catch { return default(T); } } public static bool ToOrDefault (this IConvertible obj, out T newObj) { try { newObj = To (obj); return true; } catch { newObj = default(T); return false; } } public static T ToOrOther (this IConvertible obj, T other) { try { return To obj); } catch { return other; } } public static bool ToOrOther (this IConvertible obj, out T newObj, T other) { try { newObj = To (obj); return true; } catch { newObj = other; return false; } } public static T ToOrNull (this IConvertible obj) where T : class { try { return To (obj); } catch { return null; } } public static bool ToOrNull (this IConvertible obj, out T newObj) where T : class { try { newObj = To (obj); return true; } catch { newObj = null; return false; } }
您可以在失败时请求默认值(调用空白构造函数或"0"表示数字),指定"默认"值(我称之为"其他"),或者请求null(其中T:class).我还提供了两个静默异常模型,以及一个返回bool的典型TryParse模型,指示所采取的操作,out参数保存新值.所以我们的代码可以做这样的事情
int i = myString.To(); string a = myInt.ToOrDefault (); //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 ();
我无法让Nullable类型非常干净地滚动到整个事物中.在我扔掉毛巾之前,我试了大约20分钟.
我有一个记录异常的扩展方法:
public static void Log(this Exception obj) { //your logging logic here }
它使用如下:
try { //Your stuff here } catch(Exception ex) { ex.Log(); }
[抱歉发布两次; 第二个是更好的设计:-)]
public static class StringExtensions { ////// Parses a string into an Enum /// ///The type of the Enum /// String value to parse ///The Enum corresponding to the stringExtensions public static T EnumParse(this string value) { return StringExtensions.EnumParse (value, false); } public static T EnumParse (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); } }
用于将字符串解析为枚举.
public enum TestEnum { Bar, Test } public class Test { public void Test() { TestEnum foo = "Test".EnumParse(); } }
幸得斯科特·多尔曼
---编辑Codeplex项目---
我问Scott Dorman是否会介意我们在Codeplex项目中发布他的代码.这是我从他那里得到的答复:
感谢SO帖子和CodePlex项目的单挑.我对这个问题提出了答案.是的,该代码实际上属于CodeProject Open License(http://www.codeproject.com/info/cpol10.aspx)下的公共域.
我在CodePlex项目中包含它没有任何问题,如果你想将我添加到项目中(用户名是sdorman),我将添加该方法以及一些额外的枚举助手方法.
我发现这个非常有用:
public static class PaulaBean { private static String paula = "Brillant"; public static String GetPaula(this T obj) { return paula; } }
您可以在CodePlex上使用它.
DateTimeExtensions
例子:
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();
gitorious.org/cadenza是我见过的一些最有用的扩展方法的完整库.
这是我经常用于演示文稿格式化的一个.
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()); }
这是罗马数字的来往.不经常使用,但可能很方便.用法:
if ("IV".IsValidRomanNumeral()) { // Do useful stuff with the number 4. } Console.WriteLine("MMMDCCCLXXXVIII".ParseRomanNumeral()); Console.WriteLine(3888.ToRomanNumeralString());
来源:
public static class RomanNumeralExtensions { private const int NumberOfRomanNumeralMaps = 13; private static readonly DictionaryromanNumerals = new Dictionary (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(); } }
处理尺寸的便捷方式:
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 }; } }
对于Winform控件:
////// Returns whether the function is being executed during design time in Visual Studio. /// 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; } ////// Sets the DropDownWidth to ensure that no item's text is cut off. /// 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用法:
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用法:
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();
我忘了提及,随意在Codeplex上使用这些...
ThrowIfArgumentIsNull是一个很好的方法来做我们都应该做的空检查.
public static class Extensions { public static void ThrowIfArgumentIsNull(this T obj, string parameterName) where T : class { if (obj == null) throw new ArgumentNullException(parameterName + " not allowed to be null"); } }
下面是使用它的方法,它适用于命名空间中的所有类或在其中使用命名空间的任何位置.
internal class Test { public Test(string input1) { input1.ThrowIfArgumentIsNull("input1"); } }
可以在CodePlex项目上使用此代码.
移动到C#时,我想念Visual Basic的With语句,所以这里:
public static void With(this T obj, Action act) { act(obj); }
以下是如何在C#中使用它:
someVeryVeryLonggggVariableName.With(x => { x.Int = 123; x.Str = "Hello"; x.Str2 = " World!"; });
节省了很多打字!
比较这个:
someVeryVeryLonggggVariableName.Int = 123; someVeryVeryLonggggVariableName.Str = "Hello"; someVeryVeryLonggggVariableName.Str2 = " World!";
放入codeplex项目
采用camelCaseWord或PascalCaseWord并将其"字形化",即camelCaseWord => camel 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, @"(?我经常将它与Capitalize结合使用
public static string Capitalize( this string word ) { return word[0].ToString( ).ToUpper( ) + word.Substring( 1 ); }用法示例
SomeEntityObject entity = DataAccessObject.GetSomeEntityObject( id ); Listproperties = entity.GetType().GetPublicNonCollectionProperties( ); // wordify the property names to act as column headers for an html table or something List columns = properties.Select( p => p.Name.Capitalize( ).Wordify( ) ).ToList( ); 免费在codeplex项目中使用
22> Vasu Balakri..:我发现这个有用
public static IEnumerableEmptyIfNull (this IEnumerable pSeq) { return pSeq ?? Enumerable.Empty (); } 它删除了调用代码中的空检查.你现在可以做
MyList.EmptyIfNull().Where(....)
23> CMS..:将double转换为使用指定区域性格式化的字符串:
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)); } }例:
double test = 154.20; string testString = test.ToCurrency("en-US"); // $154.20
你应该使用十进制货币,否则你会得到四舍五入的问题
24> Chris S..:下面是一个扩展方法,它适应Rick Strahl的代码(以及注释),以阻止您每次将其转换为字符串时猜测或读取字节数组或文本文件的字节顺序标记.
该片段允许您简单地执行:
byte[] buffer = File.ReadAllBytes(@"C:\file.txt"); string content = buffer.GetString();如果您发现任何错误,请添加评论.随意将其包含在Codeplex项目中.
public static class Extensions { ////// 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 /// /// An array of bytes to convert ///The byte as a string. 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(); } } } }
25> scobi..:这是我今天刚刚创建的.
// requires .NET 4 public static TReturn NullOr(this TIn obj, Func 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 (this TIn obj, Func func, TReturn elseValue) where TIn : class { return obj != null ? func(obj) : elseValue; } public static TReturn NullOr (this TIn obj, Func func) where TIn : class { return obj != null ? func(obj) : default(TReturn); } 它可以让你这样做:
var lname = thingy.NullOr(t => t.Name).NullOr(n => n.ToLower());哪个更流畅,(IMO)更容易阅读比这个:
var lname = (thingy != null ? thingy.Name : null) != null ? thingy.Name.ToLower() : null;
应该要求TIn是一个类,否则这整个扩展方法没有意义(值类型不能为null).使用t.Count的示例可以使用上面的扩展方法.你能再看一眼吗?
26> Adam Lassek..:在从MySqlDataReader中提取值时,我厌倦了繁琐的空值检查,因此:
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); }当然,这可以与任何SqlDataReader一起使用.
好事和Joe对如何做到这一点都有一些很好的评论,之后我有机会在不同的上下文中实现类似的东西,所以这是另一个版本:
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); }
这也应该作为IDataReader的扩展方法.
实际上,请使用IDataRecord类型的"this"参数以获得最大兼容性.在我的这个版本中,我有一个带有序号的重载,fieldName版本调用它.保存"GetOrdinal",然后按名称查找.
27> Michael Stum..:"请在接受将代码放入Codeplex项目时标记您的答案."
为什么?这个网站上的所有东西都在CC-by-sa-2.5下,所以只需将你的扩展溢出项目置于相同的许可下,你就可以自由使用它了.
无论如何,这是一个String.Reverse函数,基于这个问题.
////// Reverse a String /// /// The string to Reverse ///The reversed String public static string Reverse(this string input) { char[] array = input.ToCharArray(); Array.Reverse(array); return new string(array); }
希望您不会遇到任何代理人或组合人物.
28> Joel Mueller..:令我恼火的是,LINQ给了我一个OrderBy,它接受一个实现IComparer作为参数的类,但不支持传入一个简单的匿名比较器函数.我纠正了这一点.
这个类从比较器函数创建一个IComparer ...
////// Creates an internal class ComparerFactoryinstance for the given /// delegate function. /// : IComparer { public static IComparer Create(Func comparison) { return new ComparerFactory (comparison); } private readonly Func _comparison; private ComparerFactory(Func comparison) { _comparison = comparison; } #region IComparer Members public int Compare(T x, T y) { return _comparison(x, y); } #endregion } ...并且这些扩展方法在枚举上公开了我的新OrderBy重载.我怀疑它适用于LINQ to SQL,但它对于LINQ to Objects非常有用.
public static class EnumerableExtensions { ////// Sorts the elements of a sequence in ascending order by using a specified comparison delegate. /// public static IOrderedEnumerableOrderBy (this IEnumerable source, Func keySelector, Func comparison) { var comparer = ComparerFactory .Create(comparison); return source.OrderBy(keySelector, comparer); } /// /// Sorts the elements of a sequence in descending order by using a specified comparison delegate. /// public static IOrderedEnumerableOrderByDescending (this IEnumerable source, Func keySelector, Func comparison) { var comparer = ComparerFactory .Create(comparison); return source.OrderByDescending(keySelector, comparer); } } 如果你愿意,欢迎你把它放在codeplex上.
29> Eric Schoono..:这个适用于MVC,它增加了为每个可用
的
Html
变量生成标记的功能ViewPage
.希望它对试图开发类似扩展的其他人有用.使用:
<%= Html.Label("LabelId", "ForId", "Text")%>输出:
码:
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, IDictionaryhtmlAttributes) { 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 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); } }
30> Max Toro..:转过来:
DbCommand command = connection.CreateCommand(); command.CommandText = "SELECT @param"; DbParameter param = command.CreateParameter(); param.ParameterName = "@param"; param.Value = "Hello World"; command.Parameters.Add(param);......进入这个:
DbCommand command = connection.CreateCommand("SELECT {0}", "Hello World");...使用此扩展方法:
using System; using System.Data.Common; using System.Globalization; using System.Reflection; namespace DbExtensions { public static class Db { static readonly FuncgetDbProviderFactory; static readonly Func getParameterName; static readonly Func getParameterPlaceholder; static Db() { getDbProviderFactory = (Func )Delegate.CreateDelegate(typeof(Func ), typeof(DbConnection).GetProperty("DbProviderFactory", BindingFlags.Instance | BindingFlags.NonPublic).GetGetMethod(true)); getParameterName = (Func )Delegate.CreateDelegate(typeof(Func ), typeof(DbCommandBuilder).GetMethod("GetParameterName", BindingFlags.Instance | BindingFlags.NonPublic, Type.DefaultBinder, new Type[] { typeof(Int32) }, null)); getParameterPlaceholder = (Func )Delegate.CreateDelegate(typeof(Func ), 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; } } } 更多ADO.NET扩展方法:DbExtensions
31> mattmc3..:我最喜欢的一个是String上的IsLike()扩展.IsLike()匹配VB的Like运算符,当你不想编写一个完整的正则表达式来解决你的问题时,它很方便.用法是这样的:
"abc".IsLike("a*"); // true "Abc".IsLike("[A-Z][a-z][a-z]"); // true "abc123".IsLike("*###"); // true "hat".IsLike("?at"); // true "joe".IsLike("[!aeiou]*"); // true "joe".IsLike("?at"); // false "joe".IsLike("[A-Z][a-z][a-z]"); // false这是代码
public static class StringEntentions { ////// Indicates whether the current string matches the supplied wildcard pattern. Behaves the same /// as VB's "Like" Operator. /// /// The string instance where the extension method is called /// The wildcard pattern to match. Syntax matches VB's Like operator. ///true if the string matches the supplied pattern, false otherwise. ///See http://msdn.microsoft.com/en-us/library/swf8kaxw(v=VS.100).aspx public static bool IsLike(this string s, string wildcardPattern) { if (s == null || String.IsNullOrEmpty(wildcardPattern)) return false; // turn into regex pattern, and match the whole string with ^$ var regexPattern = "^" + Regex.Escape(wildcardPattern) + "$"; // add support for ?, #, *, [], and [!] regexPattern = regexPattern.Replace(@"\[!", "[^") .Replace(@"\[", "[") .Replace(@"\]", "]") .Replace(@"\?", ".") .Replace(@"\*", ".*") .Replace(@"\#", @"\d"); var result = false; try { result = Regex.IsMatch(s, regexPattern); } catch (ArgumentException ex) { throw new ArgumentException(String.Format("Invalid pattern: {0}", wildcardPattern), ex); } return result; } }
32> 小智..:在此处查找更多示例:www.extensionmethod.net
33> johnc..:类似于上面的字符串As和Is,但是对所有对象都是全局的.
这很简单,但是我用这些来减轻拳击的parens爆炸.
public static class ExtensionMethods_Object { [DebuggerStepThrough()] public static bool Is(this object item) where T : class { return item is T; } [DebuggerStepThrough()] public static bool IsNot (this object item) where T : class { return !(item.Is ()); } [DebuggerStepThrough()] public static T As (this object item) where T : class { return item as T; } } 我很高兴这个代码在codeplex中使用,实际上它已经是.
@Kamarey这是一个主观偏好,但它可以减少在你有多个演员阵容时可能会产生的混乱局面.如果您需要使用项目作为强制类型,则类型变为(项目类型)或((类型)项目).另外,从左到右扫描item.As()....在一些令人困惑的情况下,比拳击更具可读性.我确实说它很简单,我同意它是主观的,但我发现它在代码可读性方面非常强大.
34> TWith2Sugars..:对我来说另一个有用的:
////// Converts any type in to an Int32 /// ///Any Object /// Value to convert ///The integer, 0 if unsuccessful public static int ToInt32(this T value) { int result; if (int.TryParse(value.ToString(), out result)) { return result; } return 0; } /// /// Converts any type in to an Int32 but if null then returns the default /// /// Value to convert ///Any Object /// Default to use ///The defaultValue if unsuccessful public static int ToInt32(this T value, int defaultValue) { int result; if (int.TryParse(value.ToString(), out result)) { return result; } return defaultValue; } 例:
int number = "123".ToInt32();要么:
int badNumber = "a".ToInt32(100); // Returns 100 since a is nan
Convert.ToInt32(对象)?
如果我记得正确转换.ToIt32可能会抛出异常
35> jpbochi..:
IEnumerable<>
拖曳我用Fisher-Yates算法实现了一个shuffle函数.
通过
yield return
在两个函数中使用和破坏代码,它实现了正确的参数验证和延迟执行.(谢谢Dan,我在第一个版本中指出了这个缺陷)static public IEnumerableShuffle (this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); return ShuffleIterator(source); } static private IEnumerable ShuffleIterator (this IEnumerable source) { T[] array = source.ToArray(); Random rnd = new Random(); for (int n = array.Length; n > 1;) { int k = rnd.Next(n--); // 0 <= k < n //Swap items if (n != k) { T tmp = array[k]; array[k] = array[n]; array[n] = tmp; } } foreach (var item in array) yield return item; }
36> Dan Tao..:你可以从
Random
课堂上获得很多功能.以下是我不时使用的一些扩展方法.有了这些,除了
Next
与NextDouble
中,Random
类为您NextBool
,NextChar
,NextDateTime
,NextTimeSpan
,NextDouble
(接受minValue
和maxValue
参数),以及我个人最喜欢的:NextString
.有多种(NextByte
,NextShort
,NextLong
等); 但这些主要是为了完整性,并没有得到那么多的使用.所以我没有在这里包含它们(这段代码足够长,因为它!).// todo: implement additional CharType values (e.g., AsciiAny) public enum CharType { AlphabeticLower, AlphabeticUpper, AlphabeticAny, AlphanumericLower, AlphanumericUpper, AlphanumericAny, Numeric } public static class RandomExtensions { // 10 digits vs. 52 alphabetic characters (upper & lower); // probability of being numeric: 10 / 62 = 0.1612903225806452 private const double AlphanumericProbabilityNumericAny = 10.0 / 62.0; // 10 digits vs. 26 alphabetic characters (upper OR lower); // probability of being numeric: 10 / 36 = 0.2777777777777778 private const double AlphanumericProbabilityNumericCased = 10.0 / 36.0; public static bool NextBool(this Random random, double probability) { return random.NextDouble() <= probability; } public static bool NextBool(this Random random) { return random.NextDouble() <= 0.5; } public static char NextChar(this Random random, CharType mode) { switch (mode) { case CharType.AlphabeticAny: return random.NextAlphabeticChar(); case CharType.AlphabeticLower: return random.NextAlphabeticChar(false); case CharType.AlphabeticUpper: return random.NextAlphabeticChar(true); case CharType.AlphanumericAny: return random.NextAlphanumericChar(); case CharType.AlphanumericLower: return random.NextAlphanumericChar(false); case CharType.AlphanumericUpper: return random.NextAlphanumericChar(true); case CharType.Numeric: return random.NextNumericChar(); default: return random.NextAlphanumericChar(); } } public static char NextChar(this Random random) { return random.NextChar(CharType.AlphanumericAny); } private static char NextAlphanumericChar(this Random random, bool uppercase) { bool numeric = random.NextBool(AlphanumericProbabilityNumericCased); if (numeric) return random.NextNumericChar(); else return random.NextAlphabeticChar(uppercase); } private static char NextAlphanumericChar(this Random random) { bool numeric = random.NextBool(AlphanumericProbabilityNumericAny); if (numeric) return random.NextNumericChar(); else return random.NextAlphabeticChar(random.NextBool()); } private static char NextAlphabeticChar(this Random random, bool uppercase) { if (uppercase) return (char)random.Next(65, 91); else return (char)random.Next(97, 123); } private static char NextAlphabeticChar(this Random random) { return random.NextAlphabeticChar(random.NextBool()); } private static char NextNumericChar(this Random random) { return (char)random.Next(48, 58); } public static DateTime NextDateTime(this Random random, DateTime minValue, DateTime maxValue) { return DateTime.FromOADate( random.NextDouble(minValue.ToOADate(), maxValue.ToOADate()) ); } public static DateTime NextDateTime(this Random random) { return random.NextDateTime(DateTime.MinValue, DateTime.MaxValue); } public static double NextDouble(this Random random, double minValue, double maxValue) { if (maxValue < minValue) throw new ArgumentException("Minimum value must be less than maximum value."); double difference = maxValue - minValue; if (!double.IsInfinity(difference)) return minValue + (random.NextDouble() * difference); else { // to avoid evaluating to Double.Infinity, we split the range into two halves: double halfDifference = (maxValue * 0.5) - (minValue * 0.5); // 50/50 chance of returning a value from the first or second half of the range if (random.NextBool()) return minValue + (random.NextDouble() * halfDifference); else return (minValue + halfDifference) + (random.NextDouble() * halfDifference); } } public static string NextString(this Random random, int numChars, CharType mode) { char[] chars = new char[numChars]; for (int i = 0; i < numChars; ++i) chars[i] = random.NextChar(mode); return new string(chars); } public static string NextString(this Random random, int numChars) { return random.NextString(numChars, CharType.AlphanumericAny); } public static TimeSpan NextTimeSpan(this Random random, TimeSpan minValue, TimeSpan maxValue) { return TimeSpan.FromMilliseconds( random.NextDouble(minValue.TotalMilliseconds, maxValue.TotalMilliseconds) ); } public static TimeSpan NextTimeSpan(this Random random) { return random.NextTimeSpan(TimeSpan.MinValue, TimeSpan.MaxValue); } }
37> Jay Bazuzi..:我很失望.NET Framework更喜欢将文件和目录表示为字符串而不是对象,并且FileInfo和DirectoryInfo类型不像我希望的那样强大.所以,我开始编写流畅的扩展方法,因为我需要它们,例如:
public static FileInfo SetExtension(this FileInfo fileInfo, string extension) { return new FileInfo(Path.ChangeExtension(fileInfo.FullName, extension)); } public static FileInfo SetDirectory(this FileInfo fileInfo, string directory) { return new FileInfo(Path.Combine(directory, fileInfo.Name)); }是的,你可以把它放在codeplex中
38> 小智..:一些我最好的方法扩展(我有很多!):
public static T ToEnum(this string str) where T : struct { return (T)Enum.Parse(typeof(T), str); } //DayOfWeek sunday = "Sunday".ToEnum (); public static string ToString (this IEnumerable collection, string separator) { return ToString(collection, t => t.ToString(), separator); } public static string ToString (this IEnumerable collection, Func stringElement, string separator) { StringBuilder sb = new StringBuilder(); foreach (var item in collection) { sb.Append(stringElement(item)); sb.Append(separator); } return sb.ToString(0, Math.Max(0, sb.Length - separator.Length)); // quita el ultimo separador } //new []{1,2,3}.ToString(i=>i*2, ", ") --> "2, 4, 6" 此外,接下来的几乎意味着能够在几乎任何情况下继续在同一行,而不是声明新的变量,然后删除状态:
public static R Map(this T t, Func func) { return func(t); } ExpensiveFindWally().Map(wally=>wally.FirstName + " " + wally.LastName) public static R TryCC (this T t, Func func) where T : class where R : class { if (t == null) return null; return func(t); } public static R? TryCS (this T t, Func func) where T : class where R : struct { if (t == null) return null; return func(t); } public static R? TryCS (this T t, Func func) where T : class where R : struct { if (t == null) return null; return func(t); } public static R TrySC (this T? t, Func func) where T : struct where R : class { if (t == null) return null; return func(t.Value); } public static R? TrySS (this T? t, Func func) where T : struct where R : struct { if (t == null) return null; return func(t.Value); } public static R? TrySS (this T? t, Func func) where T : struct where R : struct { if (t == null) return null; return func(t.Value); } //int? bossNameLength = Departament.Boss.TryCC(b=>b.Name).TryCS(s=>s.Length); public static T ThrowIfNullS (this T? t, string mensaje) where T : struct { if (t == null) throw new NullReferenceException(mensaje); return t.Value; } public static T ThrowIfNullC (this T t, string mensaje) where T : class { if (t == null) throw new NullReferenceException(mensaje); return t; } public static T Do (this T t, Action action) { action(t); return t; } //Button b = new Button{Content = "Click"}.Do(b=>Canvas.SetColumn(b,2)); public static T TryDo (this T t, Action action) where T : class { if (t != null) action(t); return t; } public static T? TryDoS (this T? t, Action action) where T : struct { if (t != null) action(t.Value); return t; } 希望它看起来不像来自火星:)
39> Rinat Abdull..:与Timespan相关的扩展,例如:
public static TimeSpan Seconds(this int seconds) { return TimeSpan.FromSeconds(seconds); } public static TimeSpan Minutes(this int minutes) { return TimeSpan.FromMinutes(minutes); }允许使用:
1.Seconds() 20.Minutes()锁定扩展名如:
public static IDisposable GetReadLock(this ReaderWriterLockSlim slimLock) { slimLock.EnterReadLock(); return new DisposableAction(slimLock.ExitReadLock); } public static IDisposable GetWriteLock(this ReaderWriterLockSlim slimLock) { slimLock.EnterWriteLock(); return new DisposableAction(slimLock.ExitWriteLock); } public static IDisposable GetUpgradeableReadLock(this ReaderWriterLockSlim slimLock) { slimLock.EnterUpgradeableReadLock(); return new DisposableAction(slimLock.ExitUpgradeableReadLock); }允许使用锁定:
using (lock.GetUpgradeableReadLock()) { // try read using (lock.GetWriteLock()) { //do write } }以及Lokad共享图书馆的其他许多内容
40> Konamiman..:我在Silverlight项目中使用这些:
public static void Show(this UIElement element) { element.Visibility = Visibility.Visible; } public static void Hide(this UIElement element) { element.Visibility = Visibility.Collapsed; }
41> Pure.Krome..:HTH.这些是我的一些主要内容.
using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; namespace Insert.Your.Namespace.Here.Helpers { public static class Extensions { public static bool IsNullOrEmpty(this IEnumerable iEnumerable) { // Cheers to Joel Mueller for the bugfix. Was .Count(), now it's .Any() return iEnumerable == null || !iEnumerable.Any(); } public static IList ToListIfNotNullOrEmpty (this IList iList) { return iList.IsNullOrEmpty() ? null : iList; } public static PagedList ToPagedListIfNotNullOrEmpty (this PagedList pagedList) { return pagedList.IsNullOrEmpty() ? null : pagedList; } public static string ToPluralString(this int value) { return value == 1 ? string.Empty : "s"; } public static string ToReadableTime(this DateTime value) { TimeSpan span = DateTime.Now.Subtract(value); const string plural = "s"; if (span.Days > 7) { return value.ToShortDateString(); } switch (span.Days) { case 0: switch (span.Hours) { case 0: if (span.Minutes == 0) { return span.Seconds <= 0 ? "now" : string.Format("{0} second{1} ago", span.Seconds, span.Seconds != 1 ? plural : string.Empty); } return string.Format("{0} minute{1} ago", span.Minutes, span.Minutes != 1 ? plural : string.Empty); default: return string.Format("{0} hour{1} ago", span.Hours, span.Hours != 1 ? plural : string.Empty); } default: return string.Format("{0} day{1} ago", span.Days, span.Days != 1 ? plural : string.Empty); } } public static string ToShortGuidString(this Guid value) { return Convert.ToBase64String(value.ToByteArray()) .Replace("/", "_") .Replace("+", "-") .Substring(0, 22); } public static Guid FromShortGuidString(this string value) { return new Guid(Convert.FromBase64String(value.Replace("_", "/") .Replace("-", "+") + "==")); } public static string ToStringMaximumLength(this string value, int maximumLength) { return ToStringMaximumLength(value, maximumLength, "..."); } public static string ToStringMaximumLength(this string value, int maximumLength, string postFixText) { if (string.IsNullOrEmpty(postFixText)) { throw new ArgumentNullException("postFixText"); } return value.Length > maximumLength ? string.Format(CultureInfo.InvariantCulture, "{0}{1}", value.Substring(0, maximumLength - postFixText.Length), postFixText) : value; } public static string SlugDecode(this string value) { return value.Replace("_", " "); } public static string SlugEncode(this string value) { return value.Replace(" ", "_"); } } }
在IsNullOrEmpty上,我讨厌在一个百万项的枚举器上调用它.它会循环遍历所有百万项,只是为了告诉我它不是空的.更好:返回iEnumerable == null || !iEnumerable.Any();
42> TraumaPony..:public static class EnumerableExtensions { [Pure] public static U MapReduce(this IEnumerable enumerable, Func map, Func reduce) { CodeContract.RequiresAlways(enumerable != null); CodeContract.RequiresAlways(enumerable.Skip(1).Any()); CodeContract.RequiresAlways(map != null); CodeContract.RequiresAlways(reduce != null); return enumerable.AsParallel().Select(map).Aggregate(reduce); } [Pure] public static U MapReduce (this IList list, Func map, Func reduce) { CodeContract.RequiresAlways(list != null); CodeContract.RequiresAlways(list.Count >= 2); CodeContract.RequiresAlways(map != null); CodeContract.RequiresAlways(reduce != null); U result = map(list[0]); for (int i = 1; i < list.Count; i++) { result = reduce(result,map(list[i])); } return result; } //Parallel version; creates garbage [Pure] public static U MapReduce (this IList list, Func map, Func reduce) { CodeContract.RequiresAlways(list != null); CodeContract.RequiresAlways(list.Skip(1).Any()); CodeContract.RequiresAlways(map != null); CodeContract.RequiresAlways(reduce != null); U[] mapped = new U[list.Count]; Parallel.For(0, mapped.Length, i => { mapped[i] = map(list[i]); }); U result = mapped[0]; for (int i = 1; i < list.Count; i++) { result = reduce(result, mapped[i]); } return result; } }
通过在合同检查中调用"Count"来枚举"可枚举"是不是有点危险?或者这不是运行时检查?
43> Kenny Eliass..:有时,使用自定义分隔符在列表中的选定元素上写出字符串非常方便.
例如,如果你有一个
List
并想要用逗号分隔出姓氏,你可以这样做.string result = string.Empty; foreach (var person in personList) { result += person.LastName + ", "; } result = result.Substring(0, result.Length - 2); return result;或者你可以使用这个方便的扩展方法
public static string Join(this IEnumerable collection, Func func, string separator) { return String.Join(separator, collection.Select(func).ToArray()); } 并像这样使用它
personList.Join(x => x.LastName, ", ");它产生相同的结果,在这种情况下是由逗号分隔的姓氏列表.
44> Thomas Leves..:二进制搜索:
public static T BinarySearch(this IList list, Func keySelector, TKey key) where TKey : IComparable { int min = 0; int max = list.Count; int index = 0; while (min < max) { int mid = (max + min) / 2; T midItem = list[mid]; TKey midKey = keySelector(midItem); int comp = midKey.CompareTo(key); if (comp < 0) { min = mid + 1; } else if (comp > 0) { max = mid - 1; } else { return midItem; } } if (min == max && keySelector(list[min]).CompareTo(key) == 0) { return list[min]; } throw new InvalidOperationException("Item not found"); } 用法(假设列表按Id排序):
var item = list.BinarySearch(i => i.Id, 42);抛出InvalidOperationException这一事实可能看起来很奇怪,但这就是Enumerable.First在没有匹配项时所做的事情.
45> Mark Rushako..:到目前为止,我刚刚浏览了所有这4页,我感到非常惊讶,因为我没有看到这种缩短支票的方法
InvokeRequired
:using System; using System.Windows.Forms; ////// Extension methods acting on Control objects. /// internal static class ControlExtensionMethods { ////// Invokes the given action on the given control's UI thread, if invocation is needed. /// /// Control on whose UI thread to possibly invoke. /// Action to be invoked on the given control. public static void MaybeInvoke(this Control control, Action action) { if (control != null && control.InvokeRequired) { control.Invoke(action); } else { action(); } } ////// Maybe Invoke a Func that returns a value. /// ///Return type of func. /// Control on which to maybe invoke. /// Function returning a value, to invoke. ///The result of the call to func. public static T MaybeInvoke(this Control control, Func func) { if (control != null && control.InvokeRequired) { return (T)(control.Invoke(func)); } else { return func(); } } } 用法:
myForm.MaybeInvoke(() => this.Text = "Hello world"); // Sometimes the control might be null, but that's okay. var dialogResult = this.Parent.MaybeInvoke(() => MessageBox.Show(this, "Yes or no?", "Choice", MessageBoxButtons.YesNo));
46> benPearce..:一些日期功能:
public static bool IsFuture(this DateTime date, DateTime from) { return date.Date > from.Date; } public static bool IsFuture(this DateTime date) { return date.IsFuture(DateTime.Now); } public static bool IsPast(this DateTime date, DateTime from) { return date.Date < from.Date; } public static bool IsPast(this DateTime date) { return date.IsPast(DateTime.Now); }
47> bruno conde..:通过OS文件系统信息比较文件/目录的功能.这对于比较共享本地文件很有用.
用法:
DirectoryInfo dir = new DirectoryInfo(@"C:\test\myShareDir"); Console.WriteLine(dir.IsSameFileAs(@"\\myMachineName\myShareDir")); FileInfo file = new FileInfo(@"C:\test\myShareDir\file.txt"); Console.WriteLine(file.IsSameFileAs(@"\\myMachineName\myShareDir\file.txt"));码:
public static class FileExtensions { struct BY_HANDLE_FILE_INFORMATION { public uint FileAttributes; public System.Runtime.InteropServices.ComTypes.FILETIME CreationTime; public System.Runtime.InteropServices.ComTypes.FILETIME LastAccessTime; public System.Runtime.InteropServices.ComTypes.FILETIME LastWriteTime; public uint VolumeSerialNumber; public uint FileSizeHigh; public uint FileSizeLow; public uint NumberOfLinks; public uint FileIndexHigh; public uint FileIndexLow; } // // CreateFile constants // const uint FILE_SHARE_READ = 0x00000001; const uint OPEN_EXISTING = 3; const uint GENERIC_READ = (0x80000000); const uint FILE_FLAG_BACKUP_SEMANTICS = 0x02000000; [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr CreateFile( string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile); [DllImport("kernel32.dll", SetLastError = true)] static extern bool GetFileInformationByHandle(IntPtr hFile, out BY_HANDLE_FILE_INFORMATION lpFileInformation); public static bool IsSameFileAs(this FileSystemInfo file, string path) { BY_HANDLE_FILE_INFORMATION fileInfo1, fileInfo2; IntPtr ptr1 = CreateFile(file.FullName, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero); if ((int)ptr1 == -1) { System.ComponentModel.Win32Exception e = new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); throw e; } IntPtr ptr2 = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero); if ((int)ptr2 == -1) { System.ComponentModel.Win32Exception e = new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); throw e; } GetFileInformationByHandle(ptr1, out fileInfo1); GetFileInformationByHandle(ptr2, out fileInfo2); return ((fileInfo1.FileIndexHigh == fileInfo2.FileIndexHigh) && (fileInfo1.FileIndexLow == fileInfo2.FileIndexLow)); } }
你不应该关闭那些文件句柄吗?
这不是使用扩展方法.它只是一个静态类.
48> Zack Elan..:词典的Pythonic方法:
////// If a key exists in a dictionary, return its value, /// otherwise return the default value for that type. /// public static U GetWithDefault(this Dictionary dict, T key) { return dict.GetWithDefault(key, default(U)); } /// /// If a key exists in a dictionary, return its value, /// otherwise return the provided default value. /// public static U GetWithDefault(this Dictionary dict, T key, U defaultValue) { return dict.ContainsKey(key) ? dict[key] : defaultValue; } 当您想要将时间戳附加到文件名以确保唯一性时很有用.
////// Format a DateTime as a string that contains no characters //// that are banned from filenames, such as ':'. /// ///YYYY-MM-DD_HH.MM.SS public static string ToFilenameString(this DateTime dt) { return dt.ToString("s").Replace(":", ".").Replace('T', '_'); }
更好地使用TryGetValue,您正在进行两次查找而不是一次查找.
49> 小智..:我通常使用这种扩展方法使用匿名类型来获取字典ala ruby
public static DictionaryToDictionary(this object o) { var dictionary = new Dictionary (); foreach (var propertyInfo in o.GetType().GetProperties()) { if (propertyInfo.GetIndexParameters().Length == 0) { dictionary.Add(propertyInfo.Name, propertyInfo.GetValue(o, null)); } } return dictionary; } 你可以使用它
var dummy = new { color = "#000000", width = "100%", id = "myid" }; Dictionarydict = dummy.ToDictionary(); 并采用扩展方法
public static void ForEach(this IEnumerable source, Action action) { foreach (T item in source) { action(item); } } 你能行的
dummy.ToDictionary().ForEach((p) => Console.Write("{0}='{1}' ", p.Key, p.Value));产量
color ='#000000'width ='100%'id ='myid'
50> John Leidegr..:我发现自己一遍又一遍地这样做......
public static bool EqualsIgnoreCase(this string a, string b) { return string.Equals(a, b, StringComparison.OrdinalIgnoreCase); }......接着
StartsWithIgnoreCase
,EndsWithIgnoreCase
和ContainsIgnoreCase
.
51> si618..:使用密钥为字符串的字典时,使用不区分大小写的搜索返回现有密钥.我们的用例是文件路径.
////// Gets the key using ///from . /// The dictionary value. /// The dictionary. /// The case insensitive key. ////// An existing key; or public static string GetKeyIgnoringCaseif not found. /// (this IDictionary dictionary, string caseInsensitiveKey) { if (string.IsNullOrEmpty(caseInsensitiveKey)) return string.Empty; foreach (string key in dictionary.Keys) { if (key.Equals(caseInsensitiveKey, StringComparison.InvariantCultureIgnoreCase)) { return key; } } return string.Empty; }
字典中有一个单独的键集合属性,可以更快地完成此操作
如果需要不区分大小写的键,则可以将StringComparer.InvariantIgnoreCase传递给字典构造函数
52> Mark Cidade..:static string Format( this string str, , params Expression>[] args) { var parameters = args.ToDictionary ( e=>string.Format("{{{0}}}",e.Parameters[0].Name) , e=>e.Compile()(e.Parameters[0].Name)); var sb = new StringBuilder(str); foreach(var kv in parameters) { sb.Replace( kv.Key , kv.Value != null ? kv.Value.ToString() : ""); } return sb.ToString(); } 使用上面的扩展名你可以这样写:
var str = "{foo} {bar} {baz}".Format(foo=>foo, bar=>2, baz=>new object());你会得到
"foo 2 System.Object
".
53> Mark Maxham..:简单但比"Enumerable.Range"更好,恕我直言:
////// Replace "Enumerable.Range(n)" with "n.Range()": /// /// iterations ///0..n-1 public static IEnumerableRange(this int n) { for (int i = 0; i < n; i++) yield return i; }
54> Jordão..:您可能已经知道扩展方法的一个有趣用法是作为一种混合.一些扩展方法,如
XmlSerializable
,几乎每个类都污染; 它对大多数人来说没有意义,比如Thread
和SqlConnection
.应该将某些功能明确地混合到想要拥有它的类中.我提出了这种类型的新表示法,带有
M
前缀.的
XmlSerializable
话,是这样的:public interface MXmlSerializable { } public static class XmlSerializable { public static string ToXml(this MXmlSerializable self) { if (self == null) throw new ArgumentNullException(); var serializer = new XmlSerializer(self.GetType()); using (var writer = new StringWriter()) { serializer.Serialize(writer, self); return writer.GetStringBuilder().ToString(); } } public static T FromXml(string xml) where T : MXmlSerializable { var serializer = new XmlSerializer(typeof(T)); return (T)serializer.Deserialize(new StringReader(xml)); } } 然后一个类将它混合在一起:
public class Customer : MXmlSerializable { public string Name { get; set; } public bool Preferred { get; set; } }用法很简单:
var customer = new Customer { Name = "Guybrush Threepwood", Preferred = true }; var xml = customer.ToXml();如果你喜欢这个想法,你可以为项目中有用的mixin创建一个新的命名空间.你怎么看?
哦,顺便说一句,我认为大多数扩展方法都应该明确地测试null.
55> scobi..:这是我们的代码库中有趣的工作.在一个工作线程上走一个可枚举的昂贵的懒惰,并通过一个可观察的结果推回结果.
public static IObservableToAsyncObservable (this IEnumerable @this) { return Observable.Create (observer => { var task = new Task(() => { try { @this.Run(observer.OnNext); observer.OnCompleted(); } catch (Exception e) { observer.OnError(e); } }); task.Start(); return () => { }; }); } 傻样品:
new DirectoryInfo(@"c:\program files") .EnumerateFiles("*", SearchOption.AllDirectories) .ToAsyncObservable() .BufferWithTime(TimeSpan.FromSeconds(0.5)) .ObserveOnDispatcher() .Subscribe( l => Console.WriteLine("{0} received", l.Count), () => Console.WriteLine("Done!")); for (;;) { Thread.Sleep(10); Dispatcher.PushFrame(new DispatcherFrame()); }显然,如果您没有使用辉煌的Reactive Extensions,这个扩展对您来说将毫无用处!
更新感谢Richard在评论中,这种扩展方法是不必要的.RX已经有一个带有IScheduler的扩展方法"ToObservable".改用它!
任何原因`enumerable.ToObservable(Scheduler.TaskPool)`都没有解决同样的问题?
56> KeithS..:这是我发现的另一对用于:
public static T ObjectWithMin(this IEnumerable sequence, Func predicate) where T : class where TResult : IComparable { if (!sequence.Any()) return null; //get the first object with its predicate value var seed = sequence.Select(x => new {Object = x, Value = predicate(x)}).FirstOrDefault(); //compare against all others, replacing the accumulator with the lesser value //tie goes to first object found return sequence.Select(x => new {Object = x, Value = predicate(x)}) .Aggregate(seed,(acc, x) => acc.Value.CompareTo(x.Value) <= 0 ? acc : x).Object; } public static T ObjectWithMax (this IEnumerable sequence, Func predicate) where T : class where TResult : IComparable { if (!sequence.Any()) return null; //get the first object with its predicate value var seed = sequence.Select(x => new {Object = x, Value = predicate(x)}).FirstOrDefault(); //compare against all others, replacing the accumulator with the greater value //tie goes to last object found return sequence.Select(x => new {Object = x, Value = predicate(x)}) .Aggregate(seed, (acc, x) => acc.Value.CompareTo(x.Value) > 0 ? acc : x).Object; } 用法:
var myObject = myList.ObjectWithMin(x=>x.PropA);这些方法基本上取代了像
var myObject = myList.OrderBy(x=>x.PropA).FirstOrDefault(); //O(nlog(n)) and unstable和
var myObject = myList.Where(x=>x.PropA == myList.Min(x=>x.PropA)).FirstOrDefault(); //O(N^2) but stable和
var minValue = myList.Min(x=>x.PropA); var myObject = myList.Where(x=>x.PropA == minValue).FirstOrDefault(); //not a one-liner, and though linear and stable it's slower (evaluates the enumerable twice)
57> HuseyinUslu..:这是一个位图扩展,可以将位图转换为灰度;
public static Bitmap GrayScale(this Bitmap bitmap) { Bitmap newBitmap = new Bitmap(bitmap.Width, bitmap.Height); Graphics g = Graphics.FromImage(newBitmap); //the grayscale ColorMatrix ColorMatrix colorMatrix = new ColorMatrix(new float[][] { new float[] {.3f, .3f, .3f, 0, 0}, new float[] {.59f, .59f, .59f, 0, 0}, new float[] {.11f, .11f, .11f, 0, 0}, new float[] {0, 0, 0, 1, 0}, new float[] {0, 0, 0, 0, 1} }); ImageAttributes attributes = new ImageAttributes(); attributes.SetColorMatrix(colorMatrix); g.DrawImage(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height), 0, 0, bitmap.Width, bitmap.Height, GraphicsUnit.Pixel, attributes); g.Dispose(); return newBitmap; }样品用法:
Bitmap grayscaled = bitmap.GrayScale()