让我们列出您发布优秀和最喜欢的extension methods的答案。
要求是必须发布完整的代码以及如何使用它的示例和说明。
基于对此主题的高度关注,我在Codeplex上设置了一个名为extensionoverflow的开源项目。
请在接受将代码放入Codeplex项目时标记您的答案。
请发布完整的源代码,而不是链接。
Codeplex新闻:
24.08.2010 Codeplex页面现在位于:http://extensionoverflow.codeplex.com/
11.11.2008 XmlSerialize / XmlDeserialize 现在是Implemented和Unit Tested。
11.11.2008仍有更多开发人员的空间。 ;-) 现在加入!
11.11.2008第三个贡献者加入ExtensionOverflow,欢迎来到BKristensen
11.11.2008 FormatWith 现在是Implemented和Unit Tested。
09.11.2008第二个贡献者加入了ExtensionOverflow。欢迎来到chakrit。
09.11.2008我们需要更多开发人员。 ; - )
09.11.2008 ThrowIfArgumentIsNull 现在{4}}和Implemented在Codeplex上。
答案 0 :(得分:232)
public static bool In<T>(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....
}
答案 1 :(得分:160)
我的MiscUtil项目中有各种扩展方法(那里有完整的源代码 - 我不打算在这里重复)。我最喜欢的,其中一些涉及其他类(如范围):
日期和时间 - 主要用于单元测试。不确定我是否会在制作中使用它们:)
var birthday = 19.June(1976);
var workingDay = 7.Hours() + 30.Minutes();
范围和踩踏 - 非常感谢Marc Gravell让operator stuff成为可能:
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应用于匿名类型(或具有适当属性的其他类型):
// <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()
推LINQ - 在这里解释需要很长时间,但要搜索它。
答案 2 :(得分:147)
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);
快速复制粘贴转到here。
你不觉得输入"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");
...
答案 3 :(得分:89)
这些有用吗?
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!");
答案 4 :(得分: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;
}
}
示例:
if (myNumber.Between(3,7))
{
// ....
}
答案 5 :(得分:58)
扩展方法:
public static void AddRange<T, S>(this ICollection<T> list, params S[] values)
where S : T
{
foreach (S value in values)
list.Add(value);
}
该方法适用于所有类型,并允许您将一系列项目作为参数添加到列表中。
示例:
var list = new List<Int32>();
list.AddRange(5, 4, 8, 4, 2);
答案 6 :(得分:55)
一定要把它放在codeplex项目中。
将对象序列化/反序列化为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.
}
}
答案 7 :(得分:46)
ForEach for 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);
}
}
天真的例子:
var buttons = GetListOfButtons() as IEnumerable<Button>;
// click all buttons
buttons.ForEach(b => b.Click());
很酷的例子:
// 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项目
答案 8 :(得分:43)
我的转换扩展程序允许您执行以下操作:
int i = myString.To<int>();
这是as posted on 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;
}
}
您可以在失败时请求默认值(调用空白构造函数或“0”表示数字),指定“默认”值(我将其称为“其他”)或请求null(其中T:class)。我还提供了两个静默异常模型,以及一个典型的TryParse模型,它返回一个指示所采取操作的bool,一个out参数保存新值。 所以我们的代码可以做这样的事情
int i = myString.To<int>();
string a = myInt.ToOrDefault<string>();
//note type inference
DateTime d = myString.ToOrOther(DateTime.MAX_VALUE);
double d;
//note type inference
bool didItGiveDefault = myString.ToOrDefault(out d);
string s = myDateTime.ToOrNull<string>();
我无法让Nullable类型非常干净地滚动到整个事物中。在我扔掉毛巾之前,我试了大约20分钟。
答案 9 :(得分:43)
我有一个记录异常的扩展方法:
public static void Log(this Exception obj)
{
//your logging logic here
}
它的用法如下:
try
{
//Your stuff here
}
catch(Exception ex)
{
ex.Log();
}
[抱歉发布两次;第二个设计得更好: - )]
答案 10 :(得分: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);
}
}
用于将字符串解析为枚举。
public enum TestEnum
{
Bar,
Test
}
public class Test
{
public void Test()
{
TestEnum foo = "Test".EnumParse<TestEnum>();
}
}
信用转到Scott Dorman
---编辑Codeplex项目---
我问Scott Dorman是否会介意我们在Codeplex项目中发布他的代码。这是我从他那里得到的答复:
感谢SO帖子和CodePlex项目的单挑。我对这个问题提出了答案。是的,该代码实际上属于CodeProject Open License(http://www.codeproject.com/info/cpol10.aspx)下的公共域。
我在CodePlex项目中包含它没有任何问题,如果你想将我添加到项目中(用户名是sdorman),我将添加该方法以及一些额外的枚举助手方法。
答案 11 :(得分:32)
我发现这个非常有用:
public static class PaulaBean
{
private static String paula = "Brillant";
public static String GetPaula<T>(this T obj) {
return paula;
}
}
您可以在CodePlex上使用它。
答案 12 :(得分:31)
示例:
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();
答案 13 :(得分:29)
gitorious.org/cadenza是我见过的一些最有用的扩展方法的完整库。
答案 14 :(得分:28)
这是我经常用于演示文稿格式化的一个。
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());
}
答案 15 :(得分:28)
这是罗马数字的来往。不经常使用,但可能很方便。用法:
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 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();
}
}
答案 16 :(得分:25)
处理尺寸的便捷方式:
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
};
}
}
答案 17 :(得分:24)
对于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));
}
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上使用这些......
答案 18 :(得分:23)
ThrowIfArgumentIsNull是一个很好的方法来做我们都应该做的空检查。
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");
}
}
以下是使用它的方法,它适用于命名空间中的所有类,或者在其中使用命名空间的任何位置。
internal class Test
{
public Test(string input1)
{
input1.ThrowIfArgumentIsNull("input1");
}
}
可以在CodePlex项目中使用此代码。
答案 19 :(得分:22)
移动到C#时我想念Visual Basic's With statement,所以在这里:
public static void With<T>(this T obj, Action<T> 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项目
答案 20 :(得分:18)
采用camelCaseWord或PascalCaseWord并对其进行“字形化”,即camelCaseWord =&gt;骆驼案例
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])" ) );
}
我经常将它与Capitalize结合使用
public static string Capitalize( this string word )
{
return word[0].ToString( ).ToUpper( ) + word.Substring( 1 );
}
使用示例
SomeEntityObject entity = DataAccessObject.GetSomeEntityObject( id );
List<PropertyInfo> properties = entity.GetType().GetPublicNonCollectionProperties( );
// wordify the property names to act as column headers for an html table or something
List<string> columns = properties.Select( p => p.Name.Capitalize( ).Wordify( ) ).ToList( );
免费在codeplex项目中使用
答案 21 :(得分:17)
我发现这个有用
public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> pSeq)
{
return pSeq ?? Enumerable.Empty<T>();
}
它删除了调用代码中的空检查。你现在可以做
MyList.EmptyIfNull().Where(....)
答案 22 :(得分:16)
将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
答案 23 :(得分:15)
下面是一个extension method,可以调整Rick Strahl's code(以及注释)来阻止每次将其转换为字节数组或文本文件时猜测或读取字节数组或文本文件的字节顺序标记字符串。
该片段允许您简单地执行:
byte[] buffer = File.ReadAllBytes(@"C:\file.txt");
string content = buffer.GetString();
如果您发现任何错误,请添加评论。随意将其包含在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();
}
}
}
}
答案 24 :(得分:15)
这是我今天刚刚创建的一个。
// 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); }
它可以让你这样做:
var lname = thingy.NullOr(t => t.Name).NullOr(n => n.ToLower());
比这更容易阅读和(IMO):
var lname = (thingy != null ? thingy.Name : null) != null
? thingy.Name.ToLower() : null;
答案 25 :(得分:14)
我从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一起使用。
对于如何做到这一点,我们都有一些好的评论,而且我有机会在不同的环境中实现类似的东西,所以这是另一个版本:
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);
}
答案 26 :(得分:14)
“请在接受将代码放入Codeplex项目时标记您的答案。”
为什么呢?这个网站上的所有东西都在CC-by-sa-2.5下,所以只需将你的扩展溢出项目放在同一个许可下,你可以自由使用它。
无论如何,这是一个String.Reverse函数,基于this question。
/// <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);
}
答案 27 :(得分:14)
令我恼火的是,LINQ给了我一个OrderBy,它将一个实现IComparer的类作为参数,但是不支持传入一个简单的匿名比较器函数。我纠正了这一点。
此类从比较器函数创建IComparer ...
/// <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
}
...并且这些扩展方法在枚举上公开了我的新OrderBy重载。我怀疑它适用于LINQ to SQL,但它对于LINQ to Objects来说很棒。
public static class EnumerableExtensions
{
/// <summary>
/// Sorts the elements of a sequence in ascending order by using a specified comparison delegate.
/// </summary>
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
Func<TKey, TKey, int> comparison)
{
var comparer = ComparerFactory<TKey>.Create(comparison);
return source.OrderBy(keySelector, comparer);
}
/// <summary>
/// Sorts the elements of a sequence in descending order by using a specified comparison delegate.
/// </summary>
public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
Func<TKey, TKey, int> comparison)
{
var comparer = ComparerFactory<TKey>.Create(comparison);
return source.OrderByDescending(keySelector, comparer);
}
}
如果你愿意,欢迎你把它放在codeplex上。
答案 28 :(得分:13)
这个适用于MVC,它增加了为每个<label />
中可用的Html
变量生成ViewPage
标记的功能。希望它对试图开发类似扩展的其他人有用。
使用:强>
<%= Html.Label("LabelId", "ForId", "Text")%>
<强>输出:强>
<label id="LabelId" for="ForId">Text</label>
<强>代码:强>
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);
}
}
答案 29 :(得分:12)
转过来:
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 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;
}
}
}
更多ADO.NET扩展方法:DbExtensions
答案 30 :(得分:11)
我最喜欢的一个是String上的IsLike()扩展。 IsLike()匹配VB's Like operator,当你不想编写一个完整的正则表达式来解决你的问题时,它很方便。用法是这样的:
"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 {
/// <summary>
/// Indicates whether the current string matches the supplied wildcard pattern. Behaves the same
/// as VB's "Like" Operator.
/// </summary>
/// <param name="s">The string instance where the extension method is called</param>
/// <param name="wildcardPattern">The wildcard pattern to match. Syntax matches VB's Like operator.</param>
/// <returns>true if the string matches the supplied pattern, false otherwise.</returns>
/// <remarks>See http://msdn.microsoft.com/en-us/library/swf8kaxw(v=VS.100).aspx</remarks>
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;
}
}
答案 31 :(得分:10)
在此处查找更多示例:www.extensionmethod.net
答案 32 :(得分:10)
与上面的字符串As和Is类似,但对所有对象都是全局的。
这很简单,但我用这些来减轻拳击事件的爆发。
public static class ExtensionMethods_Object
{
[DebuggerStepThrough()]
public static bool Is<T>(this object item) where T : class
{
return item is T;
}
[DebuggerStepThrough()]
public static bool IsNot<T>(this object item) where T : class
{
return !(item.Is<T>());
}
[DebuggerStepThrough()]
public static T As<T>(this object item) where T : class
{
return item as T;
}
}
我很高兴这个代码在codeplex中使用,实际上它已经是。
答案 33 :(得分:9)
对我来说另一个有用的:
/// <summary>
/// Converts any type in to an Int32
/// </summary>
/// <typeparam name="T">Any Object</typeparam>
/// <param name="value">Value to convert</param>
/// <returns>The integer, 0 if unsuccessful</returns>
public static int ToInt32<T>(this T value)
{
int result;
if (int.TryParse(value.ToString(), out result))
{
return result;
}
return 0;
}
/// <summary>
/// Converts any type in to an Int32 but if null then returns the default
/// </summary>
/// <param name="value">Value to convert</param>
/// <typeparam name="T">Any Object</typeparam>
/// <param name="defaultValue">Default to use</param>
/// <returns>The defaultValue if unsuccessful</returns>
public static int ToInt32<T>(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
答案 34 :(得分:9)
IEnumerable<>
随机播放我使用Fisher-Yates算法来实现一个shuffle函数。
通过使用yield return
并破坏两个函数中的代码,它实现了正确的参数验证和延迟执行。 (感谢Dan,在我的第一个版本中指出这个缺陷)
static public IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)
{
if (source == null) throw new ArgumentNullException("source");
return ShuffleIterator(source);
}
static private IEnumerable<T> ShuffleIterator<T>(this IEnumerable<T> 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;
}
答案 35 :(得分:9)
您可以从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);
}
}
答案 36 :(得分:8)
我很失望.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
答案 37 :(得分:8)
我最好的一些方法扩展(我有很多!):
public static T ToEnum<T>(this string str) where T : struct
{
return (T)Enum.Parse(typeof(T), str);
}
//DayOfWeek sunday = "Sunday".ToEnum<DayOfWeek>();
public static string ToString<T>(this IEnumerable<T> collection, string separator)
{
return ToString(collection, t => t.ToString(), separator);
}
public static string ToString<T>(this IEnumerable<T> collection, Func<T, string> 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<T, R>(this T t, Func<T, R> func)
{
return func(t);
}
ExpensiveFindWally().Map(wally=>wally.FirstName + " " + wally.LastName)
public static R TryCC<T, R>(this T t, Func<T, R> func)
where T : class
where R : class
{
if (t == null) return null;
return func(t);
}
public static R? TryCS<T, R>(this T t, Func<T, R> func)
where T : class
where R : struct
{
if (t == null) return null;
return func(t);
}
public static R? TryCS<T, R>(this T t, Func<T, R?> func)
where T : class
where R : struct
{
if (t == null) return null;
return func(t);
}
public static R TrySC<T, R>(this T? t, Func<T, R> func)
where T : struct
where R : class
{
if (t == null) return null;
return func(t.Value);
}
public static R? TrySS<T, R>(this T? t, Func<T, R> func)
where T : struct
where R : struct
{
if (t == null) return null;
return func(t.Value);
}
public static R? TrySS<T, R>(this T? t, Func<T, R?> 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<T>(this T? t, string mensaje)
where T : struct
{
if (t == null)
throw new NullReferenceException(mensaje);
return t.Value;
}
public static T ThrowIfNullC<T>(this T t, string mensaje)
where T : class
{
if (t == null)
throw new NullReferenceException(mensaje);
return t;
}
public static T Do<T>(this T t, Action<T> action)
{
action(t);
return t;
}
//Button b = new Button{Content = "Click"}.Do(b=>Canvas.SetColumn(b,2));
public static T TryDo<T>(this T t, Action<T> action) where T : class
{
if (t != null)
action(t);
return t;
}
public static T? TryDoS<T>(this T? t, Action<T> action) where T : struct
{
if (t != null)
action(t.Value);
return t;
}
希望它看起来不像来自火星:)
答案 38 :(得分:8)
与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
}
}
的许多其他人
答案 39 :(得分:8)
我在Silverlight项目中使用这些:
public static void Show(this UIElement element)
{
element.Visibility = Visibility.Visible;
}
public static void Hide(this UIElement element)
{
element.Visibility = Visibility.Collapsed;
}
答案 40 :(得分:7)
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<T>(this IEnumerable<T> iEnumerable)
{
// Cheers to Joel Mueller for the bugfix. Was .Count(), now it's .Any()
return iEnumerable == null ||
!iEnumerable.Any();
}
public static IList<T> ToListIfNotNullOrEmpty<T>(this IList<T> iList)
{
return iList.IsNullOrEmpty() ? null : iList;
}
public static PagedList<T> ToPagedListIfNotNullOrEmpty<T>(this PagedList<T> 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(" ", "_");
}
}
}
答案 41 :(得分:7)
public static class EnumerableExtensions
{
[Pure]
public static U MapReduce<T, U>(this IEnumerable<T> enumerable, Func<T, U> map, Func<U, U, U> 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<T, U>(this IList<T> list, Func<T, U> map, Func<U, U, U> 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<T, U>(this IList<T> list, Func<T, U> map, Func<U, U, U> 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;
}
}
答案 42 :(得分:7)
有时使用自定义分隔符在列表中的选定元素上写出字符串非常方便。
例如,如果您有一个List<Person>
,并希望循环使用逗号分隔的姓氏,则可以执行此操作。
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<T>(this IEnumerable<T> collection, Func<T, string> func, string separator)
{
return String.Join(separator, collection.Select(func).ToArray());
}
并像这样使用
personList.Join(x => x.LastName, ", ");
产生相同的结果,在这种情况下是由逗号分隔的姓氏列表。
答案 43 :(得分:7)
二进制搜索:
public static T BinarySearch<T, TKey>(this IList<T> list, Func<T, TKey> keySelector, TKey key)
where TKey : IComparable<TKey>
{
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在没有匹配项时所做的事情。
答案 44 :(得分:7)
到目前为止,我刚刚浏览了所有4页,我感到非常惊讶,因为我没有看到缩短InvokeRequired
支票的方法:
using System;
using System.Windows.Forms;
/// <summary>
/// Extension methods acting on Control objects.
/// </summary>
internal static class ControlExtensionMethods
{
/// <summary>
/// Invokes the given action on the given control's UI thread, if invocation is needed.
/// </summary>
/// <param name="control">Control on whose UI thread to possibly invoke.</param>
/// <param name="action">Action to be invoked on the given control.</param>
public static void MaybeInvoke(this Control control, Action action)
{
if (control != null && control.InvokeRequired)
{
control.Invoke(action);
}
else
{
action();
}
}
/// <summary>
/// Maybe Invoke a Func that returns a value.
/// </summary>
/// <typeparam name="T">Return type of func.</typeparam>
/// <param name="control">Control on which to maybe invoke.</param>
/// <param name="func">Function returning a value, to invoke.</param>
/// <returns>The result of the call to func.</returns>
public static T MaybeInvoke<T>(this Control control, Func<T> 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));
答案 45 :(得分:7)
一些日期功能:
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);
}
答案 46 :(得分:6)
通过 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));
}
}
答案 47 :(得分:6)
词典的Pythonic方法:
/// <summary>
/// If a key exists in a dictionary, return its value,
/// otherwise return the default value for that type.
/// </summary>
public static U GetWithDefault<T, U>(this Dictionary<T, U> dict, T key)
{
return dict.GetWithDefault(key, default(U));
}
/// <summary>
/// If a key exists in a dictionary, return its value,
/// otherwise return the provided default value.
/// </summary>
public static U GetWithDefault<T, U>(this Dictionary<T, U> dict, T key, U defaultValue)
{
return dict.ContainsKey(key)
? dict[key]
: defaultValue;
}
当您想要将时间戳附加到文件名以确保唯一性时非常有用。
/// <summary>
/// Format a DateTime as a string that contains no characters
//// that are banned from filenames, such as ':'.
/// </summary>
/// <returns>YYYY-MM-DD_HH.MM.SS</returns>
public static string ToFilenameString(this DateTime dt)
{
return dt.ToString("s").Replace(":", ".").Replace('T', '_');
}
答案 48 :(得分:6)
我通常使用这种扩展方法与匿名类型来获取字典ala ruby
public static Dictionary<string, object> ToDictionary(this object o)
{
var dictionary = new Dictionary<string, object>();
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" };
Dictionary<string, object> dict = dummy.ToDictionary();
使用扩展方法
public static void ForEach<T>(this IEnumerable<T> source, Action<T> 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'
答案 49 :(得分:6)
我发现自己一遍又一遍地这样做......
public static bool EqualsIgnoreCase(this string a, string b)
{
return string.Equals(a, b, StringComparison.OrdinalIgnoreCase);
}
...后跟StartsWithIgnoreCase
,EndsWithIgnoreCase
和ContainsIgnoreCase
。
答案 50 :(得分:6)
使用密钥为字符串的字典时,使用不区分大小写的搜索返回现有密钥。我们的用例是文件路径。
/// <summary>
/// Gets the key using <paramref name="caseInsensitiveKey"/> from <paramref name="dictionary"/>.
/// </summary>
/// <typeparam name="T">The dictionary value.</typeparam>
/// <param name="dictionary">The dictionary.</param>
/// <param name="caseInsensitiveKey">The case insensitive key.</param>
/// <returns>
/// An existing key; or <see cref="string.Empty"/> if not found.
/// </returns>
public static string GetKeyIgnoringCase<T>(this IDictionary<string, T> 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;
}
答案 51 :(得分:5)
static string Format( this string str,
, params Expression<Func<string,object>>[] 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
“。
答案 52 :(得分:5)
简单但比“Enumerable.Range”更好,恕我直言:
/// <summary>
/// Replace "Enumerable.Range(n)" with "n.Range()":
/// </summary>
/// <param name="n">iterations</param>
/// <returns>0..n-1</returns>
public static IEnumerable<int> Range(this int n)
{
for (int i = 0; i < n; i++)
yield return i;
}
答案 53 :(得分:5)
您可能已经知道扩展方法的一个有趣用法是kind of mixin。一些扩展方法,如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<T>(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创建一个新的命名空间。你觉得怎么样?
哦,顺便说一下,我认为大多数扩展方法都应该explicitly test for null。
答案 54 :(得分:5)
这是我们的代码库中有趣的工作。在一个工作线程上走一个昂贵的懒惰的eval,并通过一个可观察的结果推回结果。
public static IObservable<T> ToAsyncObservable<T>(this IEnumerable<T> @this)
{
return Observable.Create<T>(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,显然这个扩展对你没用!
UPDATE 感谢Richard在评论中提到这种扩展方法是不必要的。 RX已经有一个带有IScheduler的扩展方法“ToObservable”。请改用它!
答案 55 :(得分:5)
这是我发现的另一对用于:
public static T ObjectWithMin<T, TResult>(this IEnumerable<T> sequence, Func<T, TResult> 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<T, TResult>(this IEnumerable<T> sequence, Func<T, TResult> 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)
答案 56 :(得分:5)
这是一个位图扩展,可以将位图转换为灰度;
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()
答案 57 :(得分:4)
我不想添加任何已经说过的内容,所以这里有一些我没有提及过的。 (对不起,如果这太冗长了):
public static class MyExtensions
{
public static bool IsInteger(this string input)
{
int temp;
return int.TryParse(input, out temp);
}
public static bool IsDecimal(this string input)
{
decimal temp;
return decimal.TryParse(input, out temp);
}
public static int ToInteger(this string input, int defaultValue)
{
int temp;
return (int.TryParse(input, out temp)) ? temp : defaultValue;
}
public static decimal ToDecimal(this string input, decimal defaultValue)
{
decimal temp;
return (decimal.TryParse(input, out temp)) ? temp : defaultValue;
}
public static DateTime ToFirstOfTheMonth(this DateTime input)
{
return input.Date.AddDays(-1 * input.Day + 1);
}
// Intentionally returns 0 if the target date is before the input date.
public static int MonthsUntil(this DateTime input, DateTime targetDate)
{
input = input.ToFirstOfTheMonth();
targetDate = targetDate.ToFirstOfTheMonth();
int result = 0;
while (input < targetDate)
{
input = input.AddMonths(1);
result++;
}
return result;
}
// Used for backwards compatibility in a system built before my time.
public static DataTable ToDataTable(this IEnumerable input)
{
// too much code to show here right now...
}
}
答案 58 :(得分:4)
String.As<T>
,可用于将字符串值转换为某种类型(主要用于支持IConvertable的基元和类型。适用于Nullable
类型甚至枚举!
public static partial class StringExtensions
{
/// <summary>
/// Converts the string to the specified type, using the default value configured for the type.
/// </summary>
/// <typeparam name="T">Type the string will be converted to. The type must implement IConvertable.</typeparam>
/// <param name="original">The original string.</param>
/// <returns>The converted value.</returns>
public static T As<T>(this String original)
{
return As(original, CultureInfo.CurrentCulture,
default(T));
}
/// <summary>
/// Converts the string to the specified type, using the default value configured for the type.
/// </summary>
/// <typeparam name="T">Type the string will be converted to.</typeparam>
/// <param name="original">The original string.</param>
/// <param name="defaultValue">The default value to use in case the original string is null or empty, or can't be converted.</param>
/// <returns>The converted value.</returns>
public static T As<T>(this String original, T defaultValue)
{
return As(original, CultureInfo.CurrentCulture, defaultValue);
}
/// <summary>
/// Converts the string to the specified type, using the default value configured for the type.
/// </summary>
/// <typeparam name="T">Type the string will be converted to.</typeparam>
/// <param name="original">The original string.</param>
/// <param name="provider">Format provider used during the type conversion.</param>
/// <returns>The converted value.</returns>
public static T As<T>(this String original, IFormatProvider provider)
{
return As(original, provider, default(T));
}
/// <summary>
/// Converts the string to the specified type.
/// </summary>
/// <typeparam name="T">Type the string will be converted to.</typeparam>
/// <param name="original">The original string.</param>
/// <param name="provider">Format provider used during the type conversion.</param>
/// <param name="defaultValue">The default value to use in case the original string is null or empty, or can't be converted.</param>
/// <returns>The converted value.</returns>
/// <remarks>
/// If an error occurs while converting the specified value to the requested type, the exception is caught and the default is returned. It is strongly recommended you
/// do NOT use this method if it is important that conversion failures are not swallowed up.
///
/// This method is intended to be used to convert string values to primatives, not for parsing, converting, or deserializing complex types.
/// </remarks>
public static T As<T>(this String original, IFormatProvider provider,
T defaultValue)
{
T result;
Type type = typeof (T);
if (String.IsNullOrEmpty(original)) result = defaultValue;
else
{
// need to get the underlying type if T is Nullable<>.
if (type.IsNullableType())
{
type = Nullable.GetUnderlyingType(type);
}
try
{
// ChangeType doesn't work properly on Enums
result = type.IsEnum
? (T) Enum.Parse(type, original, true)
: (T) Convert.ChangeType(original, type, provider);
}
catch // HACK: what can we do to minimize or avoid raising exceptions as part of normal operation? custom string parsing (regex?) for well-known types? it would be best to know if you can convert to the desired type before you attempt to do so.
{
result = defaultValue;
}
}
return result;
}
}
这取决于Type
的另一个简单扩展名:
/// <summary>
/// Extension methods for <see cref="Type"/>.
/// </summary>
public static class TypeExtensions
{
/// <summary>
/// Returns whether or not the specified type is <see cref="Nullable{T}"/>.
/// </summary>
/// <param name="type">A <see cref="Type"/>.</param>
/// <returns>True if the specified type is <see cref="Nullable{T}"/>; otherwise, false.</returns>
/// <remarks>Use <see cref="Nullable.GetUnderlyingType"/> to access the underlying type.</remarks>
public static bool IsNullableType(this Type type)
{
if (type == null) throw new ArgumentNullException("type");
return type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof (Nullable<>));
}
}
用法:
var someInt = "1".As<int>();
var someIntDefault = "bad value".As(1); // "bad value" won't convert, so the default value 1 is returned.
var someEnum = "Sunday".As<DayOfWeek>();
someEnum = "0".As<DayOfWeek>(); // returns Sunday
var someNullableEnum = "".As<DayOfWeek?>(null); // returns a null value since "" can't be converted
答案 59 :(得分:4)
我使用这个可以为空的数字。我帮助抓住那些除以0,NaN,Infinity ......
public static bool IsNullOrDefault<T>(this T? o)
where T : struct
{
return o == null || o.Value.Equals(default(T));
}
答案 60 :(得分:4)
我发现以下扩展方法非常有用:
public static T GetService<T>(this IServiceProvider provider)
{
return (T)provider.GetService(typeof(T));
}
这使得使用IServiceProvider
界面变得更加容易。比较:
IProvideValueTarget target = (IProvideValueTarget)serviceProvider(typeof(IProvideValueTarget));
和
var target = serviceProvider.GetService<IProvideValueTarget>();
答案 61 :(得分:4)
我的建议:
public static bool IsNullOrEmpty(this ICollection obj)
{
return (obj == null || obj.Count == 0);
}
适用于集合和数组:
bool isNullOrEmpty = array.IsNullOrEmpty()
而不是
bool isNullOrEmpty = array == null || array.Length == 0;
答案 62 :(得分:4)
将List转换为数据表
public static class DataTableConverter
{
/// <summary>
/// Convert a List{T} to a DataTable.
/// </summary>
public static DataTable ToDataTable<T>(this IList<T> items)
{
var tb = new DataTable(typeof(T).Name);
PropertyInfo[] props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo prop in props)
{
Type t = GetCoreType(prop.PropertyType);
tb.Columns.Add(prop.Name, t);
}
foreach (T item in items)
{
var values = new object[props.Length];
for (int i = 0; i < props.Length; i++)
{
values[i] = props[i].GetValue(item, null);
}
tb.Rows.Add(values);
}
return tb;
}
/// <summary>
/// Determine of specified type is nullable
/// </summary>
public static bool IsNullable(Type t)
{
return !t.IsValueType || (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>));
}
/// <summary>
/// Return underlying type if type is Nullable otherwise return the type
/// </summary>
public static Type GetCoreType(Type t)
{
if (t != null && IsNullable(t))
{
if (!t.IsValueType)
{
return t;
}
else
{
return Nullable.GetUnderlyingType(t);
}
}
else
{
return t;
}
}
}
用法:
IList<MyClass> myClassList = new List<MyClass>();
DataTable myClassDataTable = myClassList.ToDataTable();
答案 63 :(得分:4)
这些扩展方法异步调用事件。他们的灵感来自this StackOverflow answer。
/// <summary>
/// Invoke an event asynchronously. Each subscriber to the event will be invoked on a separate thread.
/// </summary>
/// <param name="someEvent">The event to be invoked asynchronously.</param>
/// <param name="sender">The sender of the event.</param>
/// <param name="args">The args of the event.</param>
/// <typeparam name="TEventArgs">The type of <see cref="EventArgs"/> to be used with the event.</typeparam>
public static void InvokeAsync<TEventArgs>(this EventHandler<TEventArgs> someEvent, object sender, TEventArgs args)
where TEventArgs : EventArgs
{
if (someEvent == null)
{
return;
}
var eventListeners = someEvent.GetInvocationList();
AsyncCallback endAsyncCallback = delegate(IAsyncResult iar)
{
var ar = iar as AsyncResult;
if (ar == null)
{
return;
}
var invokedMethod = ar.AsyncDelegate as EventHandler<TEventArgs>;
if (invokedMethod != null)
{
invokedMethod.EndInvoke(iar);
}
};
foreach (EventHandler<TEventArgs> methodToInvoke in eventListeners)
{
methodToInvoke.BeginInvoke(sender, args, endAsyncCallback, null);
}
}
/// <summary>
/// Invoke an event asynchronously. Each subscriber to the event will be invoked on a separate thread.
/// </summary>
/// <param name="someEvent">The event to be invoked asynchronously.</param>
/// <param name="sender">The sender of the event.</param>
/// <param name="args">The args of the event.</param>
public static void InvokeAsync(this EventHandler someEvent, object sender, EventArgs args)
{
if (someEvent == null)
{
return;
}
var eventListeners = someEvent.GetInvocationList();
AsyncCallback endAsyncCallback = delegate(IAsyncResult iar)
{
var ar = iar as AsyncResult;
if (ar == null)
{
return;
}
var invokedMethod = ar.AsyncDelegate as EventHandler;
if (invokedMethod != null)
{
invokedMethod.EndInvoke(iar);
}
};
foreach (EventHandler methodToInvoke in eventListeners)
{
methodToInvoke.BeginInvoke(sender, args, endAsyncCallback, null);
}
}
使用:
public class Foo
{
public event EventHandler<EventArgs> Bar;
public void OnBar()
{
Bar.InvokeAsync(this, EventArgs.Empty);
}
}
请注意,在调用事件之前,您不必检查事件是否为null。 e.g:
EventHandler<EventArgs> handler = Bar;
if (handler != null)
{
// Invoke the event
}
测试:
void Main()
{
EventHandler<EventArgs> handler1 =
delegate(object sender, EventArgs args)
{
// Simulate performing work in handler1
Thread.Sleep(100);
Console.WriteLine("Handled 1");
};
EventHandler<EventArgs> handler2 =
delegate(object sender, EventArgs args)
{
// Simulate performing work in handler2
Thread.Sleep(50);
Console.WriteLine("Handled 2");
};
EventHandler<EventArgs> handler3 =
delegate(object sender, EventArgs args)
{
// Simulate performing work in handler3
Thread.Sleep(25);
Console.WriteLine("Handled 3");
};
var foo = new Foo();
foo.Bar += handler1;
foo.Bar += handler2;
foo.Bar += handler3;
foo.OnBar();
Console.WriteLine("Start executing important stuff");
// Simulate performing some important stuff here, where we don't want to
// wait around for the event handlers to finish executing
Thread.Sleep(1000);
Console.WriteLine("Finished executing important stuff");
}
调用事件将(通常)产生此输出:
开始执行重要的东西
处理3
处理2
处理1
完成执行重要的事情
如果事件是同步调用的,它将总是产生这个输出 - 并延迟执行“重要”的东西:
处理1
处理2
处理3
开始执行重要的东西
完成执行重要的事情
答案 64 :(得分:4)
我今天实际上只是blogged。它是围绕INotifyPropertyChanged
属性的强类型反应包装器。
GetPropertyValues
会在更改时返回IObservable<T>
个值,从当前值开始。如果忽略当前值,则只需在结果上调用Skip(1)
。
用法如下:
IObservable<int> values = viewModel.GetPropertyValues(x => x.IntProperty);
实现:
public static class NotifyPropertyChangeReactiveExtensions
{
// Returns the values of property (an Expression) as they change,
// starting with the current value
public static IObservable<TValue> GetPropertyValues<TSource, TValue>(
this TSource source, Expression<Func<TSource, TValue>> property)
where TSource : INotifyPropertyChanged
{
MemberExpression memberExpression = property.Body as MemberExpression;
if (memberExpression == null)
{
throw new ArgumentException(
"property must directly access a property of the source");
}
string propertyName = memberExpression.Member.Name;
Func<TSource, TValue> accessor = property.Compile();
return source.GetPropertyChangedEvents()
.Where(x => x.EventArgs.PropertyName == propertyName)
.Select(x => accessor(source))
.StartWith(accessor(source));
}
// This is a wrapper around FromEvent(PropertyChanged)
public static IObservable<IEvent<PropertyChangedEventArgs>>
GetPropertyChangedEvents(this INotifyPropertyChanged source)
{
return Observable.FromEvent<PropertyChangedEventHandler,
PropertyChangedEventArgs>(
h => new PropertyChangedEventHandler(h),
h => source.PropertyChanged += h,
h => source.PropertyChanged -= h);
}
}
答案 65 :(得分:4)
我创建了一个很好的每个扩展,它具有与jQuery的每个函数相同的行为。
它允许类似下面的内容,您可以在其中获取当前值的索引并通过返回false来突破循环:
new[] { "first", "second", "third" }.Each((value, index) =>
{
if (value.Contains("d"))
return false;
Console.Write(value);
return true;
});
这是代码
/// <summary>
/// Generic iterator function that is useful to replace a foreach loop with at your discretion. A provided action is performed on each element.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="action">Function that takes in the current value in the sequence.
/// <returns></returns>
public static IEnumerable<T> Each<T>(this IEnumerable<T> source, Action<T> action)
{
return source.Each((value, index) =>
{
action(value);
return true;
});
}
/// <summary>
/// Generic iterator function that is useful to replace a foreach loop with at your discretion. A provided action is performed on each element.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="action">Function that takes in the current value and its index in the sequence.
/// <returns></returns>
public static IEnumerable<T> Each<T>(this IEnumerable<T> source, Action<T, int> action)
{
return source.Each((value, index) =>
{
action(value, index);
return true;
});
}
/// <summary>
/// Generic iterator function that is useful to replace a foreach loop with at your discretion. A provided action is performed on each element.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="action">Function that takes in the current value in the sequence. Returns a value indicating whether the iteration should continue. So return false if you don't want to iterate anymore.</param>
/// <returns></returns>
public static IEnumerable<T> Each<T>(this IEnumerable<T> source, Func<T, bool> action)
{
return source.Each((value, index) =>
{
return action(value);
});
}
/// <summary>
/// Generic iterator function that is useful to replace a foreach loop with at your discretion. A provided action is performed on each element.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="action">Function that takes in the current value and its index in the sequence. Returns a value indicating whether the iteration should continue. So return false if you don't want to iterate anymore.</param>
/// <returns></returns>
public static IEnumerable<T> Each<T>(this IEnumerable<T> source, Func<T, int, bool> action)
{
if (source == null)
return source;
int index = 0;
foreach (var sourceItem in source)
{
if (!action(sourceItem, index))
break;
index++;
}
return source;
}
答案 66 :(得分:3)
答案 67 :(得分:3)
我在我的网站项目中使用这些,主要是使用MVC。我为 ViewData 和 TempData
撰写了一些/// <summary>
/// Checks the Request.QueryString for the specified value and returns it, if none
/// is found then the default value is returned instead
/// </summary>
public static T QueryValue<T>(this HtmlHelper helper, string param, T defaultValue) {
object value = HttpContext.Current.Request.QueryString[param] as object;
if (value == null) { return defaultValue; }
try {
return (T)Convert.ChangeType(value, typeof(T));
} catch (Exception) {
return defaultValue;
}
}
这样我就能写出类似......
的东西<% if (Html.QueryValue("login", false)) { %>
<div>Welcome Back!</div>
<% } else { %>
<%-- Render the control or something --%>
<% } %>
答案 68 :(得分:3)
字符串类的Substring方法对我来说总是觉得不合适。通常,当您执行子字符串时,您知道要从哪里开始的字符,以及您想要结束的字符串。因此,我一直觉得必须指定长度,因为第二个参数是愚蠢的。因此,我编写了自己的扩展方法。一个采用startIndex和endIndex的方法。还有一个,它接受一个startText(string)和endText(string),这样你就可以指定从哪里开始子字符串的文本,以及从哪里结束它的文本。
注意:我无法将方法命名为Substring,因为我的第一个重载采用与.NET重载相同的参数类型。因此我将它们命名为Subsetstring。随意添加到CodePlex ...
public static class StringExtensions
{
/// <summary>
/// Returns a Subset string starting at the specified start index and ending and the specified end
/// index.
/// </summary>
/// <param name="s">The string to retrieve the subset from.</param>
/// <param name="startIndex">The specified start index for the subset.</param>
/// <param name="endIndex">The specified end index for the subset.</param>
/// <returns>A Subset string starting at the specified start index and ending and the specified end
/// index.</returns>
public static string Subsetstring(this string s, int startIndex, int endIndex)
{
if (startIndex > endIndex)
{
throw new InvalidOperationException("End Index must be after Start Index.");
}
if (startIndex < 0)
{
throw new InvalidOperationException("Start Index must be a positive number.");
}
if(endIndex <0)
{
throw new InvalidOperationException("End Index must be a positive number.");
}
return s.Substring(startIndex, (endIndex - startIndex));
}
/// <summary>
/// Finds the specified Start Text and the End Text in this string instance, and returns a string
/// containing all the text starting from startText, to the begining of endText. (endText is not
/// included.)
/// </summary>
/// <param name="s">The string to retrieve the subset from.</param>
/// <param name="startText">The Start Text to begin the Subset from.</param>
/// <param name="endText">The End Text to where the Subset goes to.</param>
/// <param name="ignoreCase">Whether or not to ignore case when comparing startText/endText to the string.</param>
/// <returns>A string containing all the text starting from startText, to the begining of endText.</returns>
public static string Subsetstring(this string s, string startText, string endText, bool ignoreCase)
{
if (string.IsNullOrEmpty(startText) || string.IsNullOrEmpty(endText))
{
throw new ArgumentException("Start Text and End Text cannot be empty.");
}
string temp = s;
if (ignoreCase)
{
temp = s.ToUpperInvariant();
startText = startText.ToUpperInvariant();
endText = endText.ToUpperInvariant();
}
int start = temp.IndexOf(startText);
int end = temp.IndexOf(endText, start);
return Subsetstring(s, start, end);
}
}
用法:
string s = "This is a tester for my cool extension method!!";
s = s.Subsetstring("tester", "cool",true);
输出:“测试我的”
答案 69 :(得分:3)
在使用MVC并拥有大量if
语句时,我只关心true
或false
,并打印null
或string.Empty
in另一种情况,我想出了:
public static TResult WhenTrue<TResult>(this Boolean value, Func<TResult> expression)
{
return value ? expression() : default(TResult);
}
public static TResult WhenTrue<TResult>(this Boolean value, TResult content)
{
return value ? content : default(TResult);
}
public static TResult WhenFalse<TResult>(this Boolean value, Func<TResult> expression)
{
return !value ? expression() : default(TResult);
}
public static TResult WhenFalse<TResult>(this Boolean value, TResult content)
{
return !value ? content : default(TResult);
}
它允许我将<%= (someBool) ? "print y" : string.Empty %>
更改为<%= someBool.WhenTrue("print y") %>
。
我只在我的视图中使用它,我混合代码和HTML,在代码文件中编写“更长”的版本更加清晰恕我直言。
答案 70 :(得分:3)
答案 71 :(得分:3)
通配符字符串比较:
public static bool MatchesWildcard(this string text, string pattern)
{
int it = 0;
while (text.CharAt(it) != 0 &&
pattern.CharAt(it) != '*')
{
if (pattern.CharAt(it) != text.CharAt(it) && pattern.CharAt(it) != '?')
return false;
it++;
}
int cp = 0;
int mp = 0;
int ip = it;
while (text.CharAt(it) != 0)
{
if (pattern.CharAt(ip) == '*')
{
if (pattern.CharAt(++ip) == 0)
return true;
mp = ip;
cp = it + 1;
}
else if (pattern.CharAt(ip) == text.CharAt(it) || pattern.CharAt(ip) == '?')
{
ip++;
it++;
}
else
{
ip = mp;
it = cp++;
}
}
while (pattern.CharAt(ip) == '*')
{
ip++;
}
return pattern.CharAt(ip) == 0;
}
public static char CharAt(this string s, int index)
{
if (index < s.Length)
return s[index];
return '\0';
}
它是来自this article的C代码的直接翻译,因此CharAt
方法为字符串的结尾返回0
if (fileName.MatchesWildcard("*.cs"))
{
Console.WriteLine("{0} is a C# source file", fileName);
}
答案 72 :(得分:3)
拥有Unix TimeStamp和ISO 8601格式的日期和时间会很棒。在网站和休息服务中大量使用。
我在我的Facebook库中使用它。您可以找到来源http://github.com/prabirshrestha/FacebookSharp/blob/master/src/FacebookSharp.Core/FacebookUtils/DateUtils.cs
private static readonly DateTime EPOCH = DateTime.SpecifyKind(new DateTime(1970, 1, 1, 0, 0, 0, 0),DateTimeKind.Utc);
public static DateTime FromUnixTimestamp(long timestamp)
{
return EPOCH.AddSeconds(timestamp);
}
public static long ToUnixTimestamp(DateTime date)
{
TimeSpan diff = date.ToUniversalTime() - EPOCH;
return (long)diff.TotalSeconds;
}
public static DateTime FromIso8601FormattedDateTime(string iso8601DateTime){
return DateTime.ParseExact(iso8601DateTime, "o", System.Globalization.CultureInfo.InvariantCulture);
}
public static string ToIso8601FormattedDateTime(DateTime dateTime)
{
return dateTime.ToString("o");
}
随意在codeplex项目中使用。
答案 73 :(得分:3)
没有检查整个帖子,所以它可能已经在这里,但是:
public static class FluentOrderingExtensions
public class FluentOrderer<T> : IEnumerable<T>
{
internal List<Comparison<T>> Comparers = new List<Comparison<T>>();
internal IEnumerable<T> Source;
public FluentOrderer(IEnumerable<T> source)
{
Source = source;
}
#region Implementation of IEnumerable
public IEnumerator<T> GetEnumerator()
{
var workingArray = Source.ToArray();
Array.Sort(workingArray, IterativeComparison);
foreach(var element in workingArray) yield return element;
}
private int IterativeComparison(T a, T b)
{
foreach (var comparer in Comparers)
{
var result = comparer(a,b);
if(result != 0) return result;
}
return 0;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
public static FluentOrderer<T> OrderFluentlyBy<T,TResult>(this IEnumerable<T> source, Func<T,TResult> predicate)
where TResult : IComparable<TResult>
{
var result = new FluentOrderer<T>(source);
result.Comparers.Add((a,b)=>predicate(a).CompareTo(predicate(b)));
return result;
}
public static FluentOrderer<T> OrderFluentlyByDescending<T,TResult>(this IEnumerable<T> source, Func<T,TResult> predicate)
where TResult : IComparable<TResult>
{
var result = new FluentOrderer<T>(source);
result.Comparers.Add((a,b)=>predicate(a).CompareTo(predicate(b)) * -1);
return result;
}
public static FluentOrderer<T> ThenBy<T, TResult>(this FluentOrderer<T> source, Func<T, TResult> predicate)
where TResult : IComparable<TResult>
{
source.Comparers.Add((a, b) => predicate(a).CompareTo(predicate(b)));
return source;
}
public static FluentOrderer<T> ThenByDescending<T, TResult>(this FluentOrderer<T> source, Func<T, TResult> predicate)
where TResult : IComparable<TResult>
{
source.Comparers.Add((a, b) => predicate(a).CompareTo(predicate(b)) * -1);
return source;
}
}
用法:
var myFluentlyOrderedList = GetABunchOfComplexObjects()
.OrderFluentlyBy(x=>x.PropertyA)
.ThenByDescending(x=>x.PropertyB)
.ThenBy(x=>x.SomeMethod())
.ThenBy(x=>SomeOtherMethodAppliedTo(x))
.ToList();
...当然假设所有谓词都返回对自身具有IComparable的类型。它可以更好地使用像MergeSort这样的稳定排序而不是.NET的内置QuickSort,但它为您提供类似于SQL的可读多字段排序功能(尽管方法链可以获得,但无论如何)。您可以通过定义带有比较lambda而不是基于谓词创建它的重载来扩展它以容纳不可IComparable的成员。
编辑:一点点解释,因为评论者得到了一些提升:这组方法通过允许您按重要性的降序排序基于多个字段来改进基本的OrderBy()功能。一个真实的例子是按客户排序发票清单,然后按发票编号(或发票日期)排序。以这种顺序获取数据的其他方法要么不起作用(OrderBy()使用不稳定的排序,因此它不能被链接)或者效率低下,看起来不像你正在尝试做的那样。答案 74 :(得分:3)
我使用的两种颜色扩展,主要用于控制开发:
public static class ColorExtensions
{
// Gets a color that will be readable on top of a given background color
public static Color GetForegroundColor(this Color input)
{
// Math taken from one of the replies to
// http://stackoverflow.com/questions/2241447/make-foregroundcolor-black-or-white-depending-on-background
if (Math.Sqrt(input.R * input.R * .241 + input.G * input.G * .691 + input.B * input.B * .068) > 128)
return Color.Black;
else
return Color.White;
}
// Converts a given Color to gray
public static Color ToGray(this Color input)
{
int g = (int)(input.R * .299) + (int)(input.G * .587) + (int)(input.B * .114);
return Color.FromArgb(input.A, g, g, g);
}
}
用法:
Color foreColor = someBackColor.GetForegroundColor();
Color grayColor = someBackColor.ToGray();
答案 75 :(得分:2)
从集合中加载默认设置的简单方法(在现实生活中,我使用它来填充任何来源的设置,包括命令行,ClickOnce URL参数等):
public static void LoadFrom(this ApplicationSettingsBase settings, NameValueCollection configuration)
{
if (configuration != null)
foreach (string key in configuration.AllKeys)
if (!String.IsNullOrEmpty(key))
try
{
settings[key] = configuration.Get(key);
}
catch (SettingsPropertyNotFoundException)
{
// handle bad arguments as you wish
}
}
示例:
Settings.Default.LoadFrom(new NameValueCollection() { { "Setting1", "Value1" }, { "Setting2", "Value2" } });
答案 76 :(得分:2)
对单元测试有用:
public static IList<T> Clone<T>(this IList<T> list) where T : ICloneable
{
var ret = new List<T>(list.Count);
foreach (var item in list)
ret.Add((T)item.Clone());
// done
return ret;
}
其中一系列像TWith2Sugars,替代缩短语法:
public static long? ToNullableInt64(this string val)
{
long ret;
return Int64.TryParse(val, out ret) ? ret : new long?();
}
最后这个 - BCL中是否已经存在以下内容?
public static void Split<T>(this T[] array,
Func<T,bool> determinator,
IList<T> onTrue,
IList<T> onFalse)
{
if (onTrue == null)
onTrue = new List<T>();
else
onTrue.Clear();
if (onFalse == null)
onFalse = new List<T>();
else
onFalse.Clear();
if (determinator == null)
return;
foreach (var item in array)
{
if (determinator(item))
onTrue.Add(item);
else
onFalse.Add(item);
}
}
答案 77 :(得分:2)
我正在使用这个......
原始代码:
if (guid != Guid.Empty) return guid;
else return Guid.NewGuid();
新代码:
return guid.NewGuidIfEmpty();
扩展方法:
public static Guid NewGuidIfEmpty(this Guid uuid)
{
return (uuid != Guid.Empty ? uuid : Guid.NewGuid());
}
答案 78 :(得分:2)
在放入数据库之前解析表单输入时,这些扩展方法对我非常有用
public static int? ToInt(this string input)
{
int val;
if (int.TryParse(input, out val))
return val;
return null;
}
public static DateTime? ToDate(this string input)
{
DateTime val;
if (DateTime.TryParse(input, out val))
return val;
return null;
}
public static decimal? ToDecimal(this string input)
{
decimal val;
if (decimal.TryParse(input, out val))
return val;
return null;
}
答案 79 :(得分:2)
我喜欢这些方法来处理具有Flags属性集的枚举:
public static bool AnyOf(this object mask, object flags)
{
return ((int)mask & (int)flags) != 0;
}
public static bool AllOf(this object mask, object flags)
{
return ((int)mask & (int)flags) == (int)flags;
}
public static object SetOn(this object mask, object flags)
{
return (int)mask | (int)flags;
}
etc.
使用示例:
var options = SomeOptions.OptionA;
options = options.SetOn(OptionB);
options = options.SetOn(OptionC);
if (options.AnyOf(SomeOptions.OptionA | SomeOptions.OptionB))
{
etc.
原始方法来自本文:http://www.codeproject.com/KB/cs/masksandflags.aspx?display=Print 我只是将它们转换为扩展方法。
它们的一个问题是对象类型的参数,这意味着所有对象最终都会使用这些方法进行扩展,而理想情况下它们只应用于枚举。
<强>更新强> 根据评论,你可以绕过“签名污染”,牺牲性能,如下:
public static bool AnyOf(this Enum mask, object flags)
{
return (Convert.ToInt642(mask) & (int)flags) != 0;
}
答案 80 :(得分:2)
GetMemberName允许获取具有编译时安全性的成员名称的字符串。
public static string GetMemberName<T, TResult>(
this T anyObject,
Expression<Func<T, TResult>> expression)
{
return ((MemberExpression)expression.Body).Member.Name;
}
用法:
"blah".GetMemberName(x => x.Length); // returns "Length"
如果您没有实例,它会与非扩展静态方法结合使用:
public static string GetMemberName<T, TReturn>(
Expression<Func<T, TReturn>> expression)
where T : class
{
return ((MemberExpression)expression.Body).Member.Name;
}
但是电话当然看起来并不漂亮:
ReflectionUtility.GetMemberName((string) s => s.Length); // returns "Length"
如果需要,可以将它放在Codeplex上。
答案 81 :(得分:2)
我投入所有项目的两个小人(有些人觉得他们很傻)是:
public static bool IsNull(this object o){
return o == null;
}
和
public static bool IsNullOrEmpty(this string s){
return string.IsNullOrEmpty(s);
}
它使我的代码更流畅..
if (myClassInstance.IsNull()) //... do something
if (myString.IsNullOrEmpty()) //... do something
我认为这些会产生非常好的扩展属性;如果我们得到那些。
答案 82 :(得分:2)
将字符串的长度减少到toLength
,并在缩短的字符串末尾添加一个额外的字符串,表示该字符串已缩短(默认...
)
public static string Shorten(this string str, int toLength, string cutOffReplacement = " ...")
{
if (string.IsNullOrEmpty(str) || str.Length <= toLength)
return str;
else
return str.Remove(toLength) + cutOffReplacement;
}
答案 83 :(得分:2)
内置强制转换的FindControl:
public static T FindControl<T>(this Control control, string id) where T : Control
{
return (T)control.FindControl(id);
}
这并不奇怪,但我觉得这样可以使代码更清晰。
// With extension method
container.FindControl<TextBox>("myTextBox").SelectedValue = "Hello world!";
// Without extension method
((TextBox)container.FindControl("myTextBox")).SelectedValue = "Hello world!";
如果需要,可以将它放在codeplex项目中
答案 84 :(得分:2)
这个非常有用:
public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> selector)
{
if (first == null)
throw new ArgumentNullException("first");
if (second == null)
throw new ArgumentNullException("second");
if (selector == null)
throw new ArgumentNullException("selector");
using (var enum1 = first.GetEnumerator())
using (var enum2 = second.GetEnumerator())
{
while (enum1.MoveNext() && enum2.MoveNext())
{
yield return selector(enum1.Current, enum2.Current);
}
}
}
它已被添加到.NET 4.0中的Enumerable
类中,但将它放在3.5中很方便。
示例:
var names = new[] { "Joe", "Jane", "Jack", "John" };
var ages = new[] { 42, 22, 18, 33 };
var persons = names.Zip(ages, (n, a) => new { Name = n, Age = a });
foreach (var p in persons)
{
Console.WriteLine("{0} is {1} years old", p.Name, p.Age);
}
答案 85 :(得分:2)
每隔一个字符包裹一个字符串。
public static string WrapAt(this string str, int WrapPos)
{
if (string.IsNullOrEmpty(str))
throw new ArgumentNullException("str", "Cannot wrap a null string");
str = str.Replace("\r", "").Replace("\n", "");
if (str.Length <= WrapPos)
return str;
for (int i = str.Length; i >= 0; i--)
if (i % WrapPos == 0 && i > 0 && i != str.Length)
str = str.Insert(i, "\r\n");
return str;
}
答案 86 :(得分:2)
我已经实现了一个扩展方法包(可在http://foop.codeplex.com/获得),我的一些常用方法是:
// the most beloved extension method for me is Pipe:
<%= variable.Pipe(x => this.SomeFunction(x)).Pipe(y =>
{
...;
return this.SomeOtherFunction(y);
}) %>
var d = 28.December(2009); // some extension methods for creating DateTime
DateTime justDatePart = d.JustDate();
TimeSpan justTimePart = d.JustTime();
var nextTime = d.Add(5.Hours());
using(StreamReader reader = new StreamReader("lines-of-data-file-for-example")) {
...
// for reading streams line by line and usable in LINQ
var query = from line in reader.Lines();
where line.Contains(_today)
select new { Parts = PartsOf(line), Time = _now };
}
500.Sleep();
XmlSerialize and XmlDeserialize
IsNull and IsNotNull
IfTrue, IfFalse and Iff:
true.IfTrue(() => Console.WriteLine("it is true then!");
IfNull and IfNotNull
答案 87 :(得分:2)
ASP MVC的NullPartial HTML帮助程序。
当传递null模型时,HTML.Partial和HTML.RenderPartial将提供View的模型,如果此部分是强类型的,并且View具有不同的类型,则它将抛出异常而不是传递空引用。这些帮助器允许您指定两个不同的部分,以便您可以将null测试保留在视图之外。
您有权将其包含在Codeplex页面
public static class nullpartials
{
public static MvcHtmlString NullPartial(this HtmlHelper helper, string Partial, string NullPartial, object Model)
{
if (Model == null)
return helper.Partial(NullPartial);
else
return helper.Partial(Partial, Model);
}
public static MvcHtmlString NullPartial(this HtmlHelper helper, string Partial, string NullPartial, object Model, ViewDataDictionary viewdata)
{
if (Model == null)
return helper.Partial(NullPartial, viewdata);
else
return helper.Partial(Partial, Model, viewdata);
}
public static void RenderNullPartial(this HtmlHelper helper, string Partial, string NullPartial, object Model)
{
if (Model == null)
{
helper.RenderPartial(NullPartial);
return;
}
else
{
helper.RenderPartial(Partial, Model);
return;
}
}
public static void RenderNullPartial(this HtmlHelper helper, string Partial, string NullPartial, object Model, ViewDataDictionary viewdata)
{
if (Model == null)
{
helper.RenderPartial(NullPartial, viewdata);
return;
}
else
{
helper.RenderPartial(Partial, Model, viewdata);
return;
}
}
}
答案 88 :(得分:2)
答案 89 :(得分:2)
我最常用的扩展是可以格式化字节数组的扩展名:
/// <summary>
/// Returns a string representation of a byte array.
/// </summary>
/// <param name="bytearray">The byte array to represent.</param>
/// <param name="subdivision">The number of elements per group,
/// or 0 to not restrict it. The default is 0.</param>
/// <param name="subsubdivision">The number of elements per line,
/// or 0 to not restrict it. The default is 0.</param>
/// <param name="divider">The string dividing the individual bytes. The default is " ".</param>
/// <param name="subdivider">The string dividing the groups. The default is " ".</param>
/// <param name="subsubdivider">The string dividing the lines. The default is "\r\n".</param>
/// <param name="uppercase">Whether the representation is in uppercase hexadecimal.
/// The default is <see langword="true"/>.</param>
/// <param name="prebyte">The string to put before each byte. The default is an empty string.</param>
/// <param name="postbyte">The string to put after each byte. The default is an empty string.</param>
/// <returns>The string representation.</returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="bytearray"/> is <see langword="null"/>.
/// </exception>
public static string ToArrayString(this byte[] bytearray,
int subdivision = 0,
int subsubdivision = 0,
string divider = " ",
string subdivider = " ",
string subsubdivider = "\r\n",
bool uppercase = true,
string prebyte = "",
string postbyte = "")
{
#region Contract
if (bytearray == null)
throw new ArgumentNullException("bytearray");
#endregion
StringBuilder sb = new StringBuilder(
bytearray.Length * (2 + divider.Length + prebyte.Length + postbyte.Length) +
(subdivision > 0 ? (bytearray.Length / subdivision) * subdivider.Length : 0) +
(subsubdivision > 0 ? (bytearray.Length / subsubdivision) * subsubdivider.Length : 0));
int groupElements = (subdivision > 0 ? subdivision - 1 : -1);
int lineElements = (subsubdivision > 0 ? subsubdivision - 1 : -1);
for (long i = 0; i < bytearray.LongLength - 1; i++)
{
sb.Append(prebyte);
sb.Append(String.Format(CultureInfo.InvariantCulture, (uppercase ? "{0:X2}" : "{0:x2}"), bytearray[i]));
sb.Append(postbyte);
if (lineElements == 0)
{
sb.Append(subsubdivider);
groupElements = subdivision;
lineElements = subsubdivision;
}
else if (groupElements == 0)
{
sb.Append(subdivider);
groupElements = subdivision;
}
else
sb.Append(divider);
lineElements--;
groupElements--;
}
sb.Append(prebyte);
sb.Append(String.Format(CultureInfo.InvariantCulture, (uppercase ? "{0:X2}" : "{0:x2}"), bytearray[bytearray.LongLength - 1]));
sb.Append(postbyte);
return sb.ToString();
}
默认情况下,ToArrayString()
只是将字节数组打印为单个字节的长字符串。但是,ToArrayString(4, 16)
将字节分为四组,每行16个字节,就像在您最喜欢的十六进制编辑器中一样。以下内容很好地格式化了C#代码中使用的字节数组:
byte[] bytearray = new byte[]{ ... };
Console.Write(bytearray.ToArrayString(4, 16, ", ", ", ", ",\r\n", true, "0x"));
这是我写的,所以你可以把它放在Codeplex上。
答案 90 :(得分:2)
灵感来自String.IsNullOrEmpty
验证给定的List是null还是空
public static bool IsNullOrEmpty<TSource>(this List<TSource> src)
{
return (src == null || src.Count == 0);
}
这个是验证给定的2个文件和属性
public static bool Compare(this FileInfo f1, FileInfo f2, string propertyName)
{
try
{
PropertyInfo p1 = f1.GetType().GetProperty(propertyName);
PropertyInfo p2 = f2.GetType().GetProperty(propertyName);
if (p1.GetValue(f1, null) == p2.GetValue(f1, null))
return true;
}
catch (Exception ex)
{
return false;
}
return false;
}
并像这样使用
FileInfo fo = new FileInfo("c:\\netlog.txt");
FileInfo f1 = new FileInfo("c:\\regkey.txt");
fo.compare(f1, "CreationTime");
答案 91 :(得分:2)
简明扼要地提出事件:
public static void Raise(this EventHandler handler, object sender, EventArgs e)
{
if (handler != null)
{
handler(sender, e);
}
}
public static void Raise<T>(this EventHandler<T> handler, object sender, T e) where T : EventArgs
{
if (handler != null)
{
handler(sender, e);
}
}
用法:
public event EventHandler Bar;
public void Foo()
{
Bar.Raise(this, EventArgs.Empty);
}
对潜在的线程安全问题进行了一些讨论here。从.NET 4开始,上面的表单是线程安全的,但是如果使用旧版本则需要重新排列和一些锁定。
答案 92 :(得分:2)
我写的就像一个四元数的扩展方法,所以这里有一些我觉得特别有用的。随意实施。
public static class ControlExtenders
{
/// <summary>
/// Advanced version of find control.
/// </summary>
/// <typeparam name="T">Type of control to find.</typeparam>
/// <param name="id">Control id to find.</param>
/// <returns>Control of given type.</returns>
/// <remarks>
/// If the control with the given id is not found
/// a new control instance of the given type is returned.
/// </remarks>
public static T FindControl<T>(this Control control, string id) where T : Control
{
// User normal FindControl method to get the control
Control _control = control.FindControl(id);
// If control was found and is of the correct type we return it
if (_control != null && _control is T)
{
// Return new control
return (T)_control;
}
// Create new control instance
_control = (T)Activator.CreateInstance(typeof(T));
// Add control to source control so the
// next it is found and the value can be
// passed on itd, remember to hide it and
// set an ID so it can be found next time
if (!(_control is ExtenderControlBase))
{
_control.Visible = false;
}
_control.ID = id;
control.Controls.Add(_control);
// Use reflection to create a new instance of the control
return (T)_control;
}
}
public static class GenericListExtenders
{
/// <summary>
/// Sorts a generic list by items properties.
/// </summary>
/// <typeparam name="T">Type of collection.</typeparam>
/// <param name="list">Generic list.</param>
/// <param name="fieldName">Field to sort data on.</param>
/// <param name="sortDirection">Sort direction.</param>
/// <remarks>
/// Use this method when a dinamyc sort field is requiered. If the
/// sorting field is known manual sorting might improve performance.
/// </remarks>
public static void SortObjects<T>(this List<T> list, string fieldName, SortDirection sortDirection)
{
PropertyInfo propInfo = typeof(T).GetProperty(fieldName);
if (propInfo != null)
{
Comparison<T> compare = delegate(T a, T b)
{
bool asc = sortDirection == SortDirection.Ascending;
object valueA = asc ? propInfo.GetValue(a, null) : propInfo.GetValue(b, null);
object valueB = asc ? propInfo.GetValue(b, null) : propInfo.GetValue(a, null);
return valueA is IComparable ? ((IComparable)valueA).CompareTo(valueB) : 0;
};
list.Sort(compare);
}
}
/// <summary>
/// Creates a pagged collection from generic list.
/// </summary>
/// <typeparam name="T">Type of collection.</typeparam>
/// <param name="list">Generic list.</param>
/// <param name="sortField">Field to sort data on.</param>
/// <param name="sortDirection">Sort direction.</param>
/// <param name="from">Page from item index.</param>
/// <param name="to">Page to item index.</param>
/// <param name="copy">Creates a copy and returns a new list instead of changing the current one.</param>
/// <returns>Pagged list collection.</returns>
public static List<T> Page<T>(this List<T> list, string sortField, bool sortDirection, int from, int to, bool copy)
{
List<T> _pageList = new List<T>();
// Copy list
if (copy)
{
T[] _arrList = new T[list.Count];
list.CopyTo(_arrList);
_pageList = new List<T>(_arrList);
}
else
{
_pageList = list;
}
// Make sure there are enough items in the list
if (from > _pageList.Count)
{
int diff = Math.Abs(from - to);
from = _pageList.Count - diff;
}
if (to > _pageList.Count)
{
to = _pageList.Count;
}
// Sort items
if (!string.IsNullOrEmpty(sortField))
{
SortDirection sortDir = SortDirection.Descending;
if (!sortDirection) sortDir = SortDirection.Ascending;
_pageList.SortObjects(sortField, sortDir);
}
// Calculate max number of items per page
int count = to - from;
if (from + count > _pageList.Count) count -= (from + count) - _pageList.Count;
// Get max number of items per page
T[] pagged = new T[count];
_pageList.CopyTo(from, pagged, 0, count);
// Return pagged items
return new List<T>(pagged);
}
/// <summary>
/// Shuffle's list items.
/// </summary>
/// <typeparam name="T">List type.</typeparam>
/// <param name="list">Generic list.</param>
public static void Shuffle<T>(this List<T> list)
{
Random rng = new Random();
for (int i = list.Count - 1; i > 0; i--)
{
int swapIndex = rng.Next(i + 1);
if (swapIndex != i)
{
T tmp = list[swapIndex];
list[swapIndex] = list[i];
list[i] = tmp;
}
}
}
/// <summary>
/// Converts generic List to DataTable.
/// </summary>
/// <typeparam name="T">Type.</typeparam>
/// <param name="list">Generic list.</param>
/// <param name="columns">Name of the columns to copy to the DataTable.</param>
/// <returns>DataTable.</returns>
public static DataTable ToDataTable<T>(this List<T> list, string[] columns)
{
List<string> _columns = new List<string>(columns);
DataTable dt = new DataTable();
foreach (PropertyInfo info in typeof(T).GetProperties())
{
if (_columns.Contains(info.Name) || columns == null)
{
dt.Columns.Add(new DataColumn(info.Name, info.PropertyType));
}
}
foreach (T t in list)
{
DataRow row = dt.NewRow();
foreach (PropertyInfo info in typeof(T).GetProperties())
{
if (_columns.Contains(info.Name) || columns == null)
{
row[info.Name] = info.GetValue(t, null);
}
}
dt.Rows.Add(row);
}
return dt;
}
}
public static class DateTimeExtenders
{
/// <summary>
/// Returns number of month from a string representation.
/// </summary>
/// <returns>Number of month.</returns>
public static int MonthToNumber(this DateTime datetime, string month)
{
month = month.ToLower();
for (int i = 1; i <= 12; i++)
{
DateTime _dt = DateTime.Parse("1." + i + ".2000");
string _month = CultureInfo.InvariantCulture.DateTimeFormat.GetMonthName(i).ToLower();
if (_month == month)
{
return i;
}
}
return 0;
}
/// <summary>
/// Returns month name from month number.
/// </summary>
/// <returns>Name of month.</returns>
public static string MonthToName(this DateTime datetime, int month)
{
for (int i = 1; i <= 12; i++)
{
if (i == month)
{
return CultureInfo.InvariantCulture.DateTimeFormat.GetMonthName(i);
}
}
return "";
}
}
public static class ObjectExtender
{
public static object CloneBinary<T>(this T originalObject)
{
using (var stream = new System.IO.MemoryStream())
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(stream, originalObject);
stream.Position = 0;
return (T)binaryFormatter.Deserialize(stream);
}
}
public static object CloneObject(this object obj)
{
using (MemoryStream memStream = new MemoryStream())
{
BinaryFormatter binaryFormatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
binaryFormatter.Serialize(memStream, obj);
memStream.Position = 0;
return binaryFormatter.Deserialize(memStream);
}
}
}
public static class StringExtenders
{
/// <summary>
/// Returns string as unit.
/// </summary>
/// <param name="value">Value.</param>
/// <returns>Unit</returns>
public static Unit ToUnit(this string value)
{
// Return empty unit
if (string.IsNullOrEmpty(value))
return Unit.Empty;
// Trim value
value = value.Trim();
// Return pixel unit
if (value.EndsWith("px"))
{
// Set unit type
string _int = value.Replace("px", "");
// Try parsing to int
double _val = 0;
if (!double.TryParse(_int, out _val))
{
// Invalid value
return Unit.Empty;
}
// Return unit
return new Unit(_val, UnitType.Pixel);
}
// Return percent unit
if (value.EndsWith("%"))
{
// Set unit type
string _int = value.Replace("%", "");
// Try parsing to int
double _val = 0;
if (!double.TryParse(_int, out _val))
{
// Invalid value
return Unit.Empty;
}
// Return unit
return new Unit(_val, UnitType.Percentage);
}
// No match found
return new Unit();
}
/// <summary>
/// Returns alternative string if current string is null or empty.
/// </summary>
/// <param name="str"></param>
/// <param name="alternative"></param>
/// <returns></returns>
public static string Alternative(this string str, string alternative)
{
if (string.IsNullOrEmpty(str)) return alternative;
return str;
}
/// <summary>
/// Removes all HTML tags from string.
/// </summary>
/// <param name="html">String containing HTML tags.</param>
/// <returns>String with no HTML tags.</returns>
public static string StripHTML(this string html)
{
string nohtml = Regex.Replace(html, "<(.|\n)*?>", "");
nohtml = nohtml.Replace("\r\n", "").Replace("\n", "").Replace(" ", "").Trim();
return nohtml;
}
}
第一个是我最喜欢的,因为它可以让我取代:
Control c = this.FindControl("tbName");
if (c != null)
{
// Do something with c
customer.Name = ((TextBox)c).Text;
}
有了这个:
TextBox c = this.FindControl<TextBox>("tbName");
customer.Name = c.Text;
设置默认字符串值:
string str = "";
if (string.IsNullOrEmpty(str))
{
str = "I'm empty!";
}
变为:
str = str.Alternative("I'm empty!");
答案 93 :(得分:2)
以下是一些方法,用于提取单个属性,但不那么痛苦:
public static T GetAttribute<T>(this ICustomAttributeProvider provider, bool inherit = false, int index = 0) where T : Attribute
{
return provider.GetAttribute(typeof(T), inherit, index) as T;
}
public static Attribute GetAttribute(this ICustomAttributeProvider provider, Type type, bool inherit = false, int index = 0)
{
bool exists = provider.IsDefined(type, inherit);
if (!exists)
{
return null;
}
object[] attributes = provider.GetCustomAttributes(type, inherit);
if (attributes != null && attributes.Length != 0)
{
return attributes[index] as Attribute;
}
else
{
return null;
}
}
用法(this enum description hack的实现):
public static string GetDescription(this Enum value)
{
var fieldInfo = value.GetType().GetField(value.ToString());
var attribute = fieldInfo.GetAttribute<DescriptionAttribute>();
return attribute != null ? attribute.Description : null;
}
随意将其包含在CodePlex项目中!
答案 94 :(得分:2)
我以为我之前曾在某个地方见过这个,但在这里找不到它。 MS在IDictionary接口上有一个TryGetValue函数,但它返回一个bool并在out
参数中给出值,所以这里有一个更简单,更清晰的实现:
public static TVal GetValueOrDefault<TKey, TVal>(this IDictionary<TKey, TVal> d, TKey key) {
if (d.ContainsKey(key))
return d[key];
return default(TVal);
}
答案 95 :(得分:2)
这是我一直在使用的另一个控制扩展,虽然我不知道它是否在此之前发布过。
public static class ControlExtensions
{
public static void DoubleBuffer(this Control control)
{
// http://stackoverflow.com/questions/76993/how-to-double-buffer-net-controls-on-a-form/77233#77233
// Taxes: Remote Desktop Connection and painting: http://blogs.msdn.com/oldnewthing/archive/2006/01/03/508694.aspx
if (System.Windows.Forms.SystemInformation.TerminalServerSession) return;
System.Reflection.PropertyInfo dbProp = typeof(System.Windows.Forms.Control).GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
dbProp.SetValue(control, true, null);
}
}
用法:
this.someControl.DoubleBuffer();
答案 96 :(得分:2)
我一直在寻找一种方法来回馈社区我开发的一些东西。
这里有一些我觉得非常有用的FileInfo扩展。
/// <summary>
/// Open with default 'open' program
/// </summary>
/// <param name="value"></param>
public static Process Open(this FileInfo value)
{
if (!value.Exists)
throw new FileNotFoundException("File doesn't exist");
Process p = new Process();
p.StartInfo.FileName = value.FullName;
p.StartInfo.Verb = "Open";
p.Start();
return p;
}
/// <summary>
/// Print the file
/// </summary>
/// <param name="value"></param>
public static void Print(this FileInfo value)
{
if (!value.Exists)
throw new FileNotFoundException("File doesn't exist");
Process p = new Process();
p.StartInfo.FileName = value.FullName;
p.StartInfo.Verb = "Print";
p.Start();
}
/// <summary>
/// Send this file to the Recycle Bin
/// </summary>
/// <exception cref="File doesn't exist" />
/// <param name="value"></param>
public static void Recycle(this FileInfo value)
{
value.Recycle(false);
}
/// <summary>
/// Send this file to the Recycle Bin
/// On show, if person refuses to send file to the recycle bin,
/// exception is thrown or otherwise delete fails
/// </summary>
/// <exception cref="File doesn't exist" />
/// <exception cref="On show, if user refuses, throws exception 'The operation was canceled.'" />
/// <param name="value">File being recycled</param>
/// <param name="showDialog">true to show pop-up</param>
public static void Recycle(this FileInfo value, bool showDialog)
{
if (!value.Exists)
throw new FileNotFoundException("File doesn't exist");
if( showDialog )
FileSystem.DeleteFile
(value.FullName, UIOption.AllDialogs,
RecycleOption.SendToRecycleBin);
else
FileSystem.DeleteFile
(value.FullName, UIOption.OnlyErrorDialogs,
RecycleOption.SendToRecycleBin);
}
在用户喜欢的编辑器中打开任何文件:
new FileInfo("C:\image.jpg").Open();
打印操作系统知道如何打印的任何文件:
new FileInfo("C:\image.jpg").Print();
将任何文件发送到回收站:
Microsoft.VisualBasic
参考using Microsoft.VisualBasic.FileIO;
示例:
new FileInfo("C:\image.jpg").Recycle();
或者
// let user have a chance to cancel send to recycle bin.
new FileInfo("C:\image.jpg").Recycle(true);
答案 97 :(得分:2)
在.NET中,有IndexOf
和LastIndexOf
方法返回String
对象中匹配的第一个和最后一个匹配项的索引。我有一个扩展方法来获取第n次出现的索引:
public static partial class StringExtensions {
public static int NthIndexOf(this String str, String match, int occurrence) {
int i = 1;
int index = 0;
while (i <= occurrence &&
( index = str.IndexOf(match, index + 1) ) != -1) {
if (i == occurrence) {
// Occurrence match found!
return index;
}
i++;
}
// Match not found
return -1;
}
}
答案 98 :(得分:2)
用于 winforms 以填充comboBox:
List<MyObject> myObjects = new List<MyObject>() {
new MyObject() {Name = "a", Id = 0},
new MyObject() {Name = "b", Id = 1},
new MyObject() {Name = "c", Id = 2} }
comboBox.FillDataSource<MyObject>(myObjects, x => x.Name);
扩展方法:
/** <summary>Fills the System.Windows.Forms.ComboBox object DataSource with a
* list of T objects.</summary>
* <param name="values">The list of T objects.</param>
* <param name="displayedValue">A function to apply to each element to get the
* display value.</param>
*/
public static void FillDataSource<T>(this ComboBox comboBox, List<T> values,
Func<T, String> displayedValue) {
// Create dataTable
DataTable data = new DataTable();
data.Columns.Add("ValueMember", typeof(T));
data.Columns.Add("DisplayMember");
for (int i = 0; i < values.Count; i++) {
// For each value/displayed value
// Create new row with value & displayed value
DataRow dr = data.NewRow();
dr["ValueMember"] = values[i];
dr["DisplayMember"] = displayedValue(values[i]) ?? "";
// Add row to the dataTable
data.Rows.Add(dr);
}
// Bind datasource to the comboBox
comboBox.DataSource = data;
comboBox.ValueMember = "ValueMember";
comboBox.DisplayMember = "DisplayMember";
}
答案 99 :(得分:1)
我喜欢这些NUnit Assert扩展程序:http://svn.caffeine-it.com/openrasta/trunk/src/Rasta.Testing/AssertExtensions.cs
答案 100 :(得分:1)
这是另一个ThrowIfNull实现:
[ThreadStatic]
private static string lastMethodName = null;
[ThreadStatic]
private static int lastParamIndex = 0;
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowIfNull<T>(this T parameter)
{
var currentStackFrame = new StackFrame(1);
var props = currentStackFrame.GetMethod().GetParameters();
if (!String.IsNullOrEmpty(lastMethodName)) {
if (currentStackFrame.GetMethod().Name != lastMethodName) {
lastParamIndex = 0;
} else if (lastParamIndex >= props.Length - 1) {
lastParamIndex = 0;
} else {
lastParamIndex++;
}
} else {
lastParamIndex = 0;
}
if (!typeof(T).IsValueType) {
for (int i = lastParamIndex; i < props.Length; i++) {
if (props[i].ParameterType.IsValueType) {
lastParamIndex++;
} else {
break;
}
}
}
if (parameter == null) {
string paramName = props[lastParamIndex].Name;
throw new ArgumentNullException(paramName);
}
lastMethodName = currentStackFrame.GetMethod().Name;
}
它没有其他强制措施那么高效,但使用起来更清晰:
public void Foo()
{
Bar(1, 2, "Hello", "World"); //no exception
Bar(1, 2, "Hello", null); //exception
Bar(1, 2, null, "World"); //exception
}
public void Bar(int x, int y, string someString1, string someString2)
{
//will also work with comments removed
//x.ThrowIfNull();
//y.ThrowIfNull();
someString1.ThrowIfNull();
someString2.ThrowIfNull();
//Do something incredibly useful here!
}
将参数更改为int?也会有用。
- 比尔
答案 101 :(得分:1)
使用列表的一些扩展:
/// <summary>
/// Wrap an object in a list
/// </summary>
public static IList<T> WrapInList<T>(this T item)
{
List<T> result = new List<T>();
result.Add(item);
return result;
}
使用例如:
myList = someObject.InList();
创建包含来自一个或多个源的项的IEnumerable,以使IEnumerable更像列表。对于高性能代码而言,这可能不是一个好主意,但对于进行测试很有用:
public static IEnumerable<T> Append<T>(this IEnumerable<T> enumerable, T newItem)
{
foreach (T item in enumerable)
{
yield return item;
}
yield return newItem;
}
public static IEnumerable<T> Append<T>(this IEnumerable<T> enumerable, params T[] newItems)
{
foreach (T item in enumerable)
{
yield return item;
}
foreach (T newItem in newItems)
{
yield return newItem;
}
}
使用例如
someEnumeration = someEnumeration.Append(newItem);
其他变体是可能的 - 例如
someEnumeration = someEnumeration.Append(otherEnumeration);
如果您正在克隆项目,您可能还想克隆它们的列表:
public static IList<T> Clone<T>(this IEnumerable<T> source) where T: ICloneable
{
List<T> result = new List<T>();
foreach (T item in source)
{
result.Add((T)item.Clone());
}
return result;
}
当我使用ObservableCollection<T>
时,我通常使用AddRange方法扩展它。这里的其他答案给出了这个的实现。
如果您需要,可以将此代码放在Codeplex项目中。
答案 102 :(得分:1)
这是ASP.Net MVC操作链接帮助器方法的扩展方法,允许它使用控制器的授权属性来决定是否应该从当前用户的视图启用,禁用或隐藏链接。 我保护您不必将受限制的操作包含在“if”子句中,以检查所有视图中的用户成员身份。感谢Maarten Balliauw的想法和代码位向我展示了方式:)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Security.Principal;
using System.Web.Routing;
using System.Web.Mvc;
using System.Collections;
using System.Reflection;
namespace System.Web.Mvc.Html
{
public static class HtmlHelperExtensions
{
/// <summary>
/// Shows or hides an action link based on the user's membership status
/// and the controller's authorize attributes
/// </summary>
/// <param name="linkText">The link text.</param>
/// <param name="action">The controller action name.</param>
/// <param name="controller">The controller name.</param>
/// <returns></returns>
public static string SecurityTrimmedActionLink(
this HtmlHelper htmlHelper,
string linkText,
string action,
string controller)
{
return SecurityTrimmedActionLink(htmlHelper, linkText, action, controller, false, null);
}
/// <summary>
/// Enables, disables or hides an action link based on the user's membership status
/// and the controller's authorize attributes
/// </summary>
/// <param name="linkText">The link text.</param>
/// <param name="action">The action name.</param>
/// <param name="controller">The controller name.</param>
/// <param name="showDisabled">if set to <c>true</c> [show link as disabled -
/// using a span tag instead of an anchor tag ].</param>
/// <param name="disabledAttributeText">Use this to add attributes to the disabled
/// span tag.</param>
/// <returns></returns>
public static string SecurityTrimmedActionLink(
this HtmlHelper htmlHelper,
string linkText,
string action,
string controller,
bool showDisabled,
string disabledAttributeText)
{
if (IsAccessibleToUser(action, controller, HttpContext.Current ))
{
return htmlHelper.ActionLink(linkText, action, controller);
}
else
{
return showDisabled ?
String.Format(
"<span{1}>{0}</span>",
linkText,
disabledAttributeText==null?"":" "+disabledAttributeText
) : "";
}
}
private static IController GetControllerInstance(string controllerName)
{
Assembly assembly = Assembly.GetExecutingAssembly();
Type controllerType = GetControllerType(controllerName);
return (IController)Activator.CreateInstance(controllerType);
}
private static ArrayList GetControllerAttributes(string controllerName, HttpContext context)
{
if (context.Cache[controllerName + "_ControllerAttributes"] == null)
{
var controller = GetControllerInstance(controllerName);
context.Cache.Add(
controllerName + "_ControllerAttributes",
new ArrayList(controller.GetType().GetCustomAttributes(typeof(AuthorizeAttribute), true)),
null,
Caching.Cache.NoAbsoluteExpiration,
Caching.Cache.NoSlidingExpiration,
Caching.CacheItemPriority.Default,
null);
}
return (ArrayList)context.Cache[controllerName + "_ControllerAttributes"];
}
private static ArrayList GetMethodAttributes(string controllerName, string actionName, HttpContext context)
{
if (context.Cache[controllerName + "_" + actionName + "_ActionAttributes"] == null)
{
ArrayList actionAttrs = new ArrayList();
var controller = GetControllerInstance(controllerName);
MethodInfo[] methods = controller.GetType().GetMethods();
foreach (MethodInfo method in methods)
{
object[] attributes = method.GetCustomAttributes(typeof(ActionNameAttribute), true);
if ((attributes.Length == 0 && method.Name == actionName)
||
(attributes.Length > 0 && ((ActionNameAttribute)attributes[0]).Name == actionName))
{
actionAttrs.AddRange(method.GetCustomAttributes(typeof(AuthorizeAttribute), true));
}
}
context.Cache.Add(
controllerName + "_" + actionName + "_ActionAttributes",
actionAttrs,
null,
Caching.Cache.NoAbsoluteExpiration,
Caching.Cache.NoSlidingExpiration,
Caching.CacheItemPriority.Default,
null);
}
return (ArrayList)context.Cache[controllerName + "_" + actionName+ "_ActionAttributes"];
}
public static bool IsAccessibleToUser(string actionToAuthorize, string controllerToAuthorize, HttpContext context)
{
IPrincipal principal = context.User;
//cache the attribute list for both controller class and it's methods
ArrayList controllerAttributes = GetControllerAttributes(controllerToAuthorize, context);
ArrayList actionAttributes = GetMethodAttributes(controllerToAuthorize, actionToAuthorize, context);
if (controllerAttributes.Count == 0 && actionAttributes.Count == 0)
return true;
string roles = "";
string users = "";
if (controllerAttributes.Count > 0)
{
AuthorizeAttribute attribute = controllerAttributes[0] as AuthorizeAttribute;
roles += attribute.Roles;
users += attribute.Users;
}
if (actionAttributes.Count > 0)
{
AuthorizeAttribute attribute = actionAttributes[0] as AuthorizeAttribute;
roles += attribute.Roles;
users += attribute.Users;
}
if (string.IsNullOrEmpty(roles) && string.IsNullOrEmpty(users) && principal.Identity.IsAuthenticated)
return true;
string[] roleArray = roles.Split(',');
string[] usersArray = users.Split(',');
foreach (string role in roleArray)
{
if (role == "*" || principal.IsInRole(role))
return true;
}
foreach (string user in usersArray)
{
if (user == "*" && (principal.Identity.Name == user))
return true;
}
return false;
}
private static Type GetControllerType(string controllerName)
{
Assembly assembly = Assembly.GetExecutingAssembly();
foreach (Type type in assembly.GetTypes())
{
if (
type.BaseType!=null
&& type.BaseType.Name == "Controller"
&& (type.Name.ToUpper() == (controllerName.ToUpper() + "Controller".ToUpper())))
{
return type;
}
}
return null;
}
}
}
答案 103 :(得分:1)
相当于Python的Join方法:
/// <summary>
/// same as python 'join'
/// </summary>
/// <typeparam name="T">list type</typeparam>
/// <param name="separator">string separator </param>
/// <param name="list">list of objects to be ToString'd</param>
/// <returns>a concatenated list interleaved with separators</returns>
static public string Join<T>(this string separator, IEnumerable<T> list)
{
var sb = new StringBuilder();
bool first = true;
foreach (T v in list)
{
if (!first)
sb.Append(separator);
first = false;
if (v != null)
sb.Append(v.ToString());
}
return sb.ToString();
}
答案 104 :(得分:1)
将任何字符串转换为Int32类型
// Calls the underlying int.TryParse method to convert a string
// representation of a number to its 32-bit signed integer equivalent.
// Returns Zero if conversion fails.
public static int ToInt32(this string s)
{
int retInt;
int.TryParse(s, out retInt);
return retInt;
}
示例使用:
string s = "999";
int i = s.ToInt32();
答案 105 :(得分:1)
通用尝试:
class Program
{
static void Main(string[] args)
{
var z = 0;
var a = 0.AsDefaultFor(() => 1 / z);
Console.WriteLine(a);
Console.ReadLine();
}
}
public static class TryExtensions
{
public static T AsDefaultFor<T>(this T @this, Func<T> operation)
{
try
{
return operation();
}
catch
{
return @this;
}
}
}
如果需要,请将其放在CodePlex项目上。
答案 106 :(得分:1)
WhereIf()方法
var query = dc.Reviewer
.Where(r => r.FacilityID == facilityID)
.WhereIf(CheckBoxActive.Checked, r => r.IsActive);
public static IEnumerable<TSource> WhereIf<TSource>(
this IEnumerable<TSource> source,
bool condition, Func<TSource, bool> predicate)
{
if (condition)
return source.Where(predicate);
else
return source;
}
public static IQueryable<TSource> WhereIf<TSource>(
this IQueryable<TSource> source,
bool condition, Expression<Func<TSource, bool>> predicate)
{
if (condition)
return source.Where(predicate);
else
return source;
}
我还在Where()扩展方法中为索引谓词添加了重载。为了更有趣,添加一个包含额外“其他”谓词的风格。
答案 107 :(得分:1)
内联转换:我喜欢这个小模式。为Boolean,Double和DateTime完成了它。旨在遵循C#是和作为运算符。
public static Int32? AsInt32(this string s)
{
Int32 value;
if (Int32.TryParse(s, out value))
return value;
return null;
}
public static bool IsInt32(this string s)
{
return s.AsInt32().HasValue;
}
public static Int32 ToInt32(this string s)
{
return Int32.Parse(s);
{
答案 108 :(得分:1)
有几次我发现自己想要的东西,我认为,Groovy的“安全导航”。
来自http://groovy.codehaus.org/Statements:
如果你正在走一个复杂的物体 图表,不想拥有 你可以抛出NullPointerExceptions 使用 ?。操作员而不是。至 执行导航。
def foo = null def bar = foo?.something?.myMethod()断言吧 == null
那么,您认为为其添加扩展方法是一个好主意吗? 类似的东西:
obj.SafelyNavigate(x => x.SomeProperty.MaybeAMethod().AnotherProperty);
我认为即使它也会带来一些麻烦也会很好。
如果您认为这是一个好主意:
也许这只是一个坏主意:D,但我认为如果做得对,它可能会有用。 如果没有这样的东西,并且你认为它具有一定的价值,我可以试一试并在之后编辑答案。
答案 109 :(得分:1)
我总是使用需要StringBuilder
新行的格式,因此下面非常简单的扩展名会保存几行代码:
public static class Extensions
{
public static void AppendLine(this StringBuilder builder,string format, params object[] args)
{
builder.AppendLine(string.Format(format, args));
}
}
备选方案为AppendFormat
StringBuilder
,其中\n
或环境.NewLine。
答案 110 :(得分:1)
用于解析的模式可以避免out
个参数:
public static bool TryParseInt32(this string input, Action<int> action)
{
int result;
if (Int32.TryParse(input, out result))
{
action(result);
return true;
}
return false;
}
用法:
if (!textBox.Text.TryParseInt32(number => label.Text = SomeMathFunction(number)))
label.Text = "Please enter a valid integer";
如果需要,可以将它放在codeplex项目中
答案 111 :(得分:1)
在ASP.NET中,我总是厌倦了使用FindControl,然后在引用之前必须强制转换并检查值是否为null。所以,我向Control添加了一个TryParse()方法,它反映了Int32等框架中的类似方法。
public static bool TryParse<T>(this Control control, string id, out T result)
where T : Control
{
result = control.FindControl(id) as T;
return result != null;
}
现在,您可以在ASP.NET Web表单页面中执行此操作:
Label lbl;
if (Page.TryParse("Label1", out lbl))
{
lbl.Text = "Safely set text";
}
答案 112 :(得分:1)
一些方便的字符串助手:
<强>用法:强>
我讨厌不需要的空格尾随或引导字符串,因为字符串可以采用null
值,所以它可能很棘手,所以我使用它:
public bool IsGroup { get { return !this.GroupName.IsNullOrTrimEmpty(); } }
这是我用于新validation framework我正在试用的另一种扩展方法。您可以在其中查看正则表达式扩展,以帮助清除乱糟糟的正则表达式:
public static bool IsRequiredWithLengthLessThanOrEqualNoSpecial(this String str, int length)
{
return !str.IsNullOrTrimEmpty() &&
str.RegexMatch(
@"^[- \r\n\\\.!:*,@$%&""?\(\)\w']{1,{0}}$".RegexReplace(@"\{0\}", length.ToString()),
RegexOptions.Multiline) == str;
}
<强>来源:强>
public static class StringHelpers
{
/// <summary>
/// Same as String.IsNullOrEmpty except that
/// it captures the Empty state for whitespace
/// strings by Trimming first.
/// </summary>
public static bool IsNullOrTrimEmpty(this String helper)
{
if (helper == null)
return true;
else
return String.Empty == helper.Trim();
}
public static int TrimLength(this String helper)
{
return helper.Trim().Length;
}
/// <summary>
/// Returns the matched string from the regex pattern. The
/// groupName is for named group match values in the form (?<name>group).
/// </summary>
public static string RegexMatch(this String helper, string pattern, RegexOptions options, string groupName)
{
if (groupName.IsNullOrTrimEmpty())
return Regex.Match(helper, pattern, options).Value;
else
return Regex.Match(helper, pattern, options).Groups[groupName].Value;
}
public static string RegexMatch(this String helper, string pattern)
{
return RegexMatch(helper, pattern, RegexOptions.None, null);
}
public static string RegexMatch(this String helper, string pattern, RegexOptions options)
{
return RegexMatch(helper, pattern, options, null);
}
public static string RegexMatch(this String helper, string pattern, string groupName)
{
return RegexMatch(helper, pattern, RegexOptions.None, groupName);
}
/// <summary>
/// Returns true if there is a match from the regex pattern
/// </summary>
public static bool IsRegexMatch(this String helper, string pattern, RegexOptions options)
{
return helper.RegexMatch(pattern, options).Length > 0;
}
public static bool IsRegexMatch(this String helper, string pattern)
{
return helper.IsRegexMatch(pattern, RegexOptions.None);
}
/// <summary>
/// Returns a string where matching patterns are replaced by the replacement string.
/// </summary>
/// <param name="pattern">The regex pattern for matching the items to be replaced</param>
/// <param name="replacement">The string to replace matching items</param>
/// <returns></returns>
public static string RegexReplace(this String helper, string pattern, string replacement, RegexOptions options)
{
return Regex.Replace(helper, pattern, replacement, options);
}
public static string RegexReplace(this String helper, string pattern, string replacement)
{
return Regex.Replace(helper, pattern, replacement, RegexOptions.None);
}
}
我喜欢做很多正则表达式,所以我认为这些比添加using语句和额外代码来处理命名组更容易。
答案 113 :(得分:1)
对于ASP.NET,我使用HttpSessionState的这些扩展来加载会话中的对象。 它允许您以干净的方式加载会话对象,并且如果它们不存在,将创建并初始化它们。 我使用两种扩展方法,如:
private bool CreateMode;
private MyClass SomeClass;
protected override void OnInit (EventArgs e)
{
CreateMode = Session.GetSessionValue<bool> ("someKey1", () => true);
SomeClass = Session.GetSessionClass<MyClass> ("someKey2", () => new MyClass ()
{
MyProperty = 123
});
}
以下是扩展程序类:
public static class SessionExtensions
{
public delegate object UponCreate ();
public static T GetSessionClass<T> (this HttpSessionState session,
string key, UponCreate uponCreate) where T : class
{
if (null == session[key])
{
var item = uponCreate () as T;
session[key] = item;
return item;
}
return session[key] as T;
}
public static T GetSessionValue<T> (this HttpSessionState session,
string key, UponCreate uponCreate) where T : struct
{
if (null == session[key])
{
var item = uponCreate();
session[key] = item;
return (T)item;
}
return (T)session[key];
}
}
public static class SessionExtensions
{
public delegate object UponCreate ();
public static T GetSessionClass<T> (this HttpSessionState session,
string key, UponCreate uponCreate) where T : class
{
if (null == session[key])
{
var item = uponCreate () as T;
session[key] = item;
return item;
}
return session[key] as T;
}
public static T GetSessionValue<T> (this HttpSessionState session,
string key, UponCreate uponCreate) where T : struct
{
if (null == session[key])
{
var item = uponCreate();
session[key] = item;
return (T)item;
}
return (T)session[key];
}
}
答案 114 :(得分:1)
讨厌这种代码?
CloneableClass cc1 = new CloneableClass ();
CloneableClass cc2 = null;
CloneableClass cc3 = null;
cc3 = (CloneableClass) cc1.Clone (); // this is ok
cc3 = cc2.Clone (); // this throws null ref exception
// code to handle both cases
cc3 = cc1 != null ? (CloneableClass) cc1.Clone () : null;
它有点笨重,所以我用这个扩展名替换它,我称之为CloneOrNull -
public static T CloneOrNull<T> (this T self) where T : class, ICloneable
{
if (self == null) return null;
return (T) self.Clone ();
}
用法如下:
CloneableClass cc1 = new CloneableClass ();
CloneableClass cc2 = null;
CloneableClass cc3 = null;
cc3 = cc1.CloneOrNull (); // clone of cc1
cc3 = cc2.CloneOrNull (); // null
// look mom, no casts!
请随时随地使用!
答案 115 :(得分:1)
我一直使用: :
public static void DelimitedAppend(this StringBuilder sb, string value, string delimiter)
{
if (sb.Length > 0)
sb.Append(delimiter);
sb.Append(value);
}
这只是确保在字符串为空时不插入分隔符。 例如,要创建逗号分隔的单词列表:
var farmAnimals = new[] { new { Species = "Dog", IsTasty = false }, new { Species = "Cat", IsTasty = false }, new { Species = "Chicken", IsTasty = true }, };
var soupIngredients = new StringBuilder();
foreach (var edible in farmAnimals.Where(farmAnimal => farmAnimal.IsTasty))
soupIngredients.DelimitedAppend(edible.Species, ", ");
答案 116 :(得分:1)
如果您使用财政年度
,可以使用几个有用的扩展程序/// <summary>
/// Returns the fiscal year for the passed in date
/// </summary>
/// <param name="value">the date</param>
/// <returns>the fiscal year</returns>
public static int FiscalYear(this DateTime value)
{
int ret = value.Year;
if (value.Month >= 7) ret++;
return ret;
}
/// <summary>
/// Returns the fiscal year for the passed in date
/// </summary>
/// <param name="value">the date</param>
/// <returns>the fiscal year</returns>
public static string FiscalYearString(this DateTime value)
{
int fy = FiscalYear(value);
return "{0}/{1}".Format(fy - 1, fy);
}
答案 117 :(得分:1)
ASP.NET HTML编码 - 短而甜:
public static string ToHtmlEncodedString(this string s)
{
if (String.IsNullOrEmpty(s))
return s;
return HttpUtility.HtmlEncode(s);
}
答案 118 :(得分:1)
在指定的索引处覆盖字符串的一部分。
我必须使用一个系统,它希望某些输入值是固定宽度,固定位置字符串。
public static string Overwrite(this string s, int startIndex, string newStringValue)
{
return s.Remove(startIndex, newStringValue.Length).Insert(startIndex, newStringValue);
}
所以我能做到:
string s = new String(' ',60);
s = s.Overwrite(7,"NewValue");
答案 119 :(得分:1)
还有一个:
public enum ParseFailBehavior
{
ReturnNull,
ReturnDefault,
ThrowException
}
public static T? ParseNullableEnum<T>(this string theValue, ParseFailBehavior desiredBehavior = ParseFailBehavior.ReturnNull) where T:struct
{
T output;
T? result = Enum.TryParse<T>(theValue, out output)
? (T?)output
: desiredBehavior == ParseFailBehavior.ReturnDefault
? (T?)default(T)
: null;
if(result == null && desiredBehavior == ParseFailBehavior.ThrowException)
throw new ArgumentException("Parse Failed for value {0} of enum type {1}".
FormatWith(theValue, typeof(T).Name));
}
此版本需要.NET 4.0;在3.5你没有TryParse和没有可选参数;你必须尝试捕获Enum.Parse()。它仍然完全可以在3.5(更有用,因为Enum.Parse()是oogly和你唯一的其他选择):
public static T? ParseNummableEnum<T>(this string theValue)
{
return theValue.ParseNullableEnum<T>(ParseFailBehavior.ReturnNull);
}
public static T? ParseNullableEnum<T>(this string theValue,
ParseFailBehavior desiredBehavior) where T:struct
{
try
{
return (T?) Enum.Parse(typeof (T), theValue);
}
catch (Exception)
{
if(desiredBehavior == ParseFailBehavior.ThrowException) throw;
}
return desiredBehavior == ParseFailBehavior.ReturnDefault ? (T?)default(T) : null;
}
用法:
//returns null if OptionOne isn't an enum constant
var myEnum = "OptionOne".ParseNullableEnum<OptionEnum>();
//guarantees a return value IF the enum has a "zero" constant value (generally a good practice)
var myEnum = "OptionTwo".ParseNullableEnum<OptionEnum>(ParseFailBehavior.ReturnDefault).Value
答案 120 :(得分:1)
空格规范化非常有用,尤其是在处理用户输入时:
namespace Extensions.String
{
using System.Text.RegularExpressions;
public static class Extensions
{
/// <summary>
/// Normalizes whitespace in a string.
/// Leading/Trailing whitespace is eliminated and
/// all sequences of internal whitespace are reduced to
/// a single SP (ASCII 0x20) character.
/// </summary>
/// <param name="s">The string whose whitespace is to be normalized</param>
/// <returns>a normalized string</returns>
public static string NormalizeWS( this string @this )
{
string src = @this ?? "" ;
string normalized = rxWS.Replace( src , m =>{
bool isLeadingTrailingWS = ( m.Index == 0 || m.Index+m.Length == src.Length ? true : false ) ;
string p = ( isLeadingTrailingWS ? "" : " " ) ;
return p ;
}) ;
return normalized ;
}
private static Regex rxWS = new Regex( @"\s+" ) ;
}
}
答案 121 :(得分:1)
IEnumerable的一些工具:ToString(格式),ToString(函数)和连接(分隔符)。
例如:
var names = new[] { "Wagner", "Francine", "Arthur", "Bernardo" };
names.ToString("Name: {0}\n");
// Name: Wagner
// Name: Francine
// Name: Arthur
// Name: Bernardo
names.ToString(name => name.Length > 6 ? String.Format("{0} ", name) : String.Empty);
// Francine Bernardo
names.Join(" - ");
// Wagner - Francine - Arthur - Bernardo
扩展:
public static string ToString<T>(this IEnumerable<T> self, string format)
{
return self.ToString(i => String.Format(format, i));
}
public static string ToString<T>(this IEnumerable<T> self, Func<T, object> function)
{
var result = new StringBuilder();
foreach (var item in self) result.Append(function(item));
return result.ToString();
}
public static string Join<T>(this IEnumerable<T> self, string separator)
{
return String.Join(separator, values: self.ToArray());
}
答案 122 :(得分:1)
使用反射查找TryParse方法并在字符串目标上调用它。可选参数指定转换失败时应返回的内容。我发现这种方法在大多数情况下非常有用。很清楚Convert.ChangeType
选项,但我发现这更有用的是默认结果方便和诸如此类的东西。请注意,找到的方法保存在字典中,虽然我怀疑拳击最终减慢了一点。
这种方法是我最喜欢的,因为它合法地使用了很多语言功能。
private static readonly Dictionary<Type, MethodInfo> Parsers = new Dictionary<Type, MethodInfo>();
public static T Parse<T>(this string value, T defaultValue = default(T))
{
if (string.IsNullOrEmpty(value)) return defaultValue;
if (!Parsers.ContainsKey(typeof(T)))
Parsers[typeof (T)] = typeof (T).GetMethods(BindingFlags.Public | BindingFlags.Static)
.Where(mi => mi.Name == "TryParse")
.Single(mi =>
{
var parameters = mi.GetParameters();
if (parameters.Length != 2) return false;
return parameters[0].ParameterType == typeof (string) &&
parameters[1].ParameterType == typeof (T).MakeByRefType();
});
var @params = new object[] {value, default(T)};
return (bool) Parsers[typeof (T)].Invoke(null, @params) ?
(T) @params[1] : defaultValue;
}
用法:
var hundredTwentyThree = "123".Parse(0);
var badnumber = "test".Parse(-1);
var date = "01/01/01".Parse<DateTime>();
答案 123 :(得分:1)
有些时候需要有类的实例,无论是否有效但不是null
public static T Safe<T>(this T obj) where T : new()
{
if (obj == null)
{
obj = new T();
}
return obj;
}
用法如下:
MyClass myClass = Provider.GetSomeResult();
string temp = myClass.Safe().SomeValue;
而不是:
MyClass myClass = Provider.GetSomeResult();
string temp = "some default value";
if (myClass != null)
{
temp = myClass.SomeValue;
}
抱歉,如果它是一个两面派,但我找不到它。
答案 124 :(得分:1)
我还没有看到任何答案...
public static string[] Split(this string value, string regexPattern)
{
return value.Split(regexPattern, RegexOptions.None);
}
public static string[] Split(this string value, string regexPattern,
RegexOptions options)
{
return Regex.Split(value, regexPattern, options);
}
用法:
var obj = "test1,test2,test3";
string[] arrays = obj.Split(",");
答案 125 :(得分:0)
用于向没有AddRange的集合添加多个元素,例如collection.Add(item1, item2, itemN);
static void Add<T>(this ICollection<T> coll, params T[] items)
{ foreach (var item in items) coll.Add(item);
}
以下内容与string.Format()
类似,但使用参数的自定义字符串表示形式,例如"{0} {1} {2}".Format<Custom>(c=>c.Name,"string",new object(),new Custom())
会产生"string {System.Object} Custom1Name"
static string Format<T>( this string format
, Func<T,object> select
, params object[] args)
{ for(int i=0; i < args.Length; ++i)
{ var x = args[i] as T;
if (x != null) args[i] = select(x);
}
return string.Format(format, args);
}
答案 126 :(得分:0)
// Values ordered true/false
// True/false values separated by a capital letter
// Only two values allowed
// ---------------------------
// Limited, but could be useful
public enum BooleanFormat
{
OneZero,
YN,
YesNo,
TF,
TrueFalse,
PassFail,
YepNope
}
public static class BooleanExtension
{
/// <summary>
/// Converts the boolean value of this instance to the specified string value.
/// </summary>
private static string ToString(this bool value, string passValue, string failValue)
{
return value ? passValue : failValue;
}
/// <summary>
/// Converts the boolean value of this instance to a string.
/// </summary>
/// <param name="booleanFormat">A BooleanFormat value.
/// Example: BooleanFormat.PassFail would return "Pass" if true and "Fail" if false.</param>
/// <returns>Boolean formatted string</returns>
public static string ToString(this bool value, BooleanFormat booleanFormat)
{
string booleanFormatString = Enum.GetName(booleanFormat.GetType(), booleanFormat);
return ParseBooleanString(value, booleanFormatString);
}
// Parses boolean format strings, not optimized
private static string ParseBooleanString(bool value, string booleanFormatString)
{
StringBuilder trueString = new StringBuilder();
StringBuilder falseString = new StringBuilder();
int charCount = booleanFormatString.Length;
bool isTrueString = true;
for (int i = 0; i != charCount; i++)
{
if (char.IsUpper(booleanFormatString[i]) && i != 0)
isTrueString = false;
if (isTrueString)
trueString.Append(booleanFormatString[i]);
else
falseString.Append(booleanFormatString[i]);
}
return (value == true ? trueString.ToString() : falseString.ToString());
}
答案 127 :(得分:0)
也许我编写和使用的最有用的扩展方法是:
http://www.codeproject.com/KB/cs/fun-with-cs-extensions.aspx?msg=2838918#xx2838918xx
答案 128 :(得分:0)
// Checks for an empty collection, and sends the value set in the default constructor for the desired field
public static TResult MinGuarded<T, TResult>(this IEnumerable<T> items, Func<T, TResult> expression) where T : new() {
if(items.IsEmpty()) {
return (new List<T> { new T() }).Min(expression);
}
return items.Min(expression);
}
// Checks for an empty collection, and sends the value set in the default constructor for the desired field
public static TResult MaxGuarded<T, TResult>(this IEnumerable<T> items, Func<T, TResult> expression) where T : new() {
if(items.IsEmpty()) {
return (new List<T> { new T() }).Max(expression);
}
return items.Max(expression);
}
我不确定是否有更好的方法可以做到这一点,但只要我想控制对象中字段的默认值,这个扩展就非常有用。
例如,如果我想控制DateTime的值并希望按照我的业务逻辑进行设置,那么我可以在默认构造函数中执行此操作。否则,它会变成DateTime.MinDate
。
答案 129 :(得分:0)
Aww为什么不呢!这是IList的扩展(不能是IEnumerable,因为我使用列表特定的功能)进行插入排序。
internal static class SortingHelpers
{
/// <summary>
/// Performs an insertion sort on this list.
/// </summary>
/// <typeparam name="T">The type of the list supplied.</typeparam>
/// <param name="list">the list to sort.</param>
/// <param name="comparison">the method for comparison of two elements.</param>
/// <returns></returns>
public static void InsertionSort<T>(this IList<T> list, Comparison<T> comparison)
{
for (int i = 2; i < list.Count; i++)
{
for (int j = i; j > 1 && comparison(list[j], list[j - 1]) < 0; j--)
{
T tempItem = list[j];
list.RemoveAt(j);
list.Insert(j - 1, tempItem);
}
}
}
}
一个例子:
List<int> list1 = { 3, 5, 1, 2, 9, 4, 6 };
list1.InsertionSort((a,b) => a - b);
//list is now in order of 1,2,3,4,5,6,9
答案 130 :(得分:0)
在我博客统计信息页面的最近搜索部分中,我删除了所有重复项,但需要一种方法来删除几乎重复的行。我会得到大量类似但不完全相同的Google查询。
我最终使用匿名类型而不是字典,但想要一种方法来创建匿名类型的List。你不能这样做,但你可以在.NET 4.0中创建List<dynamic>
:)
我最喜欢它,因为我有效地获得了List<AnonymousType#1>()
。
/// <summary>Remove extraneous entries for common word permutations</summary>
/// <param name="input">Incoming series of words to be filtered</param>
/// <param name="MaxIgnoreLength">Words this long or shorter will not count as duplicates</param>
/// <param name="words2">Instance list from BuildInstanceList()</param>
/// <returns>Filtered list of lines from input, based on filter info in words2</returns>
private static List<string> FilterNearDuplicates(List<string> input, int MaxIgnoreLength, List<dynamic> words2)
{
List<string> output = new List<string>();
foreach (string line in input)
{
int Dupes = 0;
foreach (string word in line.Split(new char[] { ' ', ',', ';', '\\', '/', ':', '\"', '\r', '\n', '.' })
.Where(p => p.Length > MaxIgnoreLength)
.Distinct())
{
int Instances = 0;
foreach (dynamic dyn in words2)
if (word == dyn.Word)
{
Instances = dyn.Instances;
if (Instances > 1)
Dupes++;
break;
}
}
if (Dupes == 0)
output.Add(line);
}
return output;
}
/// <summary>Builds a list of words and how many times they occur in the overall list</summary>
/// <param name="input">Incoming series of words to be counted</param>
/// <returns></returns>
private static List<dynamic> BuildInstanceList(List<string> input)
{
List<dynamic> words2 = new List<object>();
foreach (string line in input)
foreach (string word in line.Split(new char[] { ' ', ',', ';', '\\', '/', ':', '\"', '\r', '\n', '.' }))
{
if (string.IsNullOrEmpty(word))
continue;
else if (ExistsInList(word, words2))
for (int i = words2.Count - 1; i >= 0; i--)
{
if (words2[i].Word == word)
words2[i] = new { Word = words2[i].Word, Instances = words2[i].Instances + 1 };
}
else
words2.Add(new { Word = word, Instances = 1 });
}
return words2;
}
/// <summary>Determines whether a dynamic Word object exists in a List of this dynamic type.</summary>
/// <param name="word">Word to look for</param>
/// <param name="words">Word dynamics to search through</param>
/// <returns>Indicator of whether the word exists in the list of words</returns>
private static bool ExistsInList(string word, List<dynamic> words)
{
foreach (dynamic dyn in words)
if (dyn.Word == word)
return true;
return false;
}
答案 131 :(得分:0)
使用db结果的一些DataSet / DataRow扩展更简单
只需在DataRow上使用.Field(“fieldname”),如果可以的话,它会抛出它,可以包含可选的默认值。
另外.HasRows()在DataSet上,因此您不需要检查是否存在表和行。
示例:
using (DataSet ds = yourcall())
{
if (ds.HasRows())
{
foreach (DataRow dr in ds.Tables[0].Rows)
{
int id = dr.Field<int>("ID");
string name = dr.Field<string>("Name");
string Action = dr.Field<string>("Action", "N/A");
}
}
}
代码:
using System;
using System.Data;
public static class DataSetExtensions
{
public static T Field<T>(this DataRow row, string columnName, T defaultValue)
{
try
{
return row.Field<T>(columnName);
}
catch
{
return defaultValue;
}
}
public static T Field<T>(this DataRow row, string columnName)
{
if (row[columnName] == null)
throw new NullReferenceException(columnName + " does not exist in DataRow");
string value = row[columnName].ToString();
if (typeof(T) == "".GetType())
{
return (T)Convert.ChangeType(value, typeof(T));
}
else if (typeof(T) == 0.GetType())
{
return (T)Convert.ChangeType(int.Parse(value), typeof(T));
}
else if (typeof(T) == false.GetType())
{
return (T)Convert.ChangeType(bool.Parse(value), typeof(T));
}
else if (typeof(T) == DateTime.Now.GetType())
{
return (T)Convert.ChangeType(DateTime.Parse(value), typeof(T));
}
else if (typeof(T) == new byte().GetType())
{
return (T)Convert.ChangeType(byte.Parse(value), typeof(T));
}
else if (typeof(T) == new float().GetType())
{
return (T)Convert.ChangeType(float.Parse(value), typeof(T));
}
else
{
throw new ArgumentException(string.Format("Cannot cast '{0}' to '{1}'.", value, typeof(T).ToString()));
}
}
public static bool HasRows(this DataSet dataSet)
{
return (dataSet.Tables.Count > 0 && dataSet.Tables[0].Rows.Count > 0);
}
}
答案 132 :(得分:0)
public static class StringHelper
{
public static String F(this String str, params object[] args)
{
return String.Format(str, args);
}
}
使用like:
"Say {0}".F("Hello");
答案 133 :(得分:0)
public static class DictionaryExtensions
{
public static Nullable<TValue> GetValueOrNull<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key)
where TValue : struct
{
TValue result;
if (dictionary.TryGetValue(key, out result))
return result;
else
return null;
}
}
免费使用,只需在代码中提及我的名字(JankoRöbisch)。
答案 134 :(得分:0)
// This file contains extension methods for generic List<> class to operate on sorted lists.
// Duplicate values are OK.
// O(ln(n)) is still much faster then the O(n) of LINQ's searches/filters.
static partial class SortedList
{
// Return the index of the first element with the key greater then provided.
// If there's no such element within the provided range, it returns iAfterLast.
public static int sortedFirstGreaterIndex<tElt, tKey>( this IList<tElt> list, Func<tElt, tKey, int> comparer, tKey key, int iFirst, int iAfterLast )
{
if( iFirst < 0 || iAfterLast < 0 || iFirst > list.Count || iAfterLast > list.Count )
throw new IndexOutOfRangeException();
if( iFirst > iAfterLast )
throw new ArgumentException();
if( iFirst == iAfterLast )
return iAfterLast;
int low = iFirst, high = iAfterLast;
// The code below is inspired by the following article:
// http://en.wikipedia.org/wiki/Binary_search#Single_comparison_per_iteration
while( low < high )
{
int mid = ( high + low ) / 2;
// 'mid' might be 'iFirst' in case 'iFirst+1 == iAfterLast'.
// 'mid' will never be 'iAfterLast'.
if( comparer( list[ mid ], key ) <= 0 ) // "<=" since we gonna find the first "greater" element
low = mid + 1;
else
high = mid;
}
return low;
}
// Return the index of the first element with the key greater then the provided key.
// If there's no such element, returns list.Count.
public static int sortedFirstGreaterIndex<tElt, tKey>( this IList<tElt> list, Func<tElt, tKey, int> comparer, tKey key )
{
return list.sortedFirstGreaterIndex( comparer, key, 0, list.Count );
}
// Add an element to the sorted array.
// This could be an expensive operation if frequently adding elements that sort firstly.
// This is cheap operation when adding elements that sort near the tail of the list.
public static int sortedAdd<tElt>( this List<tElt> list, Func<tElt, tElt, int> comparer, tElt elt )
{
if( list.Count == 0 || comparer( list[ list.Count - 1 ], elt ) <= 0 )
{
// either the list is empty, or the item is greater then all elements already in the collection.
list.Add( elt );
return list.Count - 1;
}
int ind = list.sortedFirstGreaterIndex( comparer, elt );
list.Insert( ind, elt );
return ind;
}
// Find first exactly equal element, return -1 if not found.
public static int sortedFindFirstIndex<tElt, tKey>( this List<tElt> list, Func<tElt, tKey, int> comparer, tKey elt )
{
int low = 0, high = list.Count - 1;
while( low < high )
{
int mid = ( high + low ) / 2;
if( comparer( list[ mid ], elt ) < 0 )
low = mid + 1;
else
high = mid; // this includes the case when we've found an element exactly matching the key
}
if( high >= 0 && 0 == comparer( list[ high ], elt ) )
return high;
return -1;
}
// Return the IEnumerable that returns array elements in the reverse order.
public static IEnumerable<tElt> sortedReverse<tElt>( this List<tElt> list )
{
for( int i=list.Count - 1; i >= 0; i-- )
yield return list[ i ];
}
}
答案 135 :(得分:0)
这个没有完全烘烤,因为我们今天早上想出来了。它将为Type生成完整的类定义。适用于您拥有大型类并且想要创建子集或完整定义但无权访问它的情况。例如,将对象存储在数据库等中。
public static class TypeExtensions
{
public static string GenerateClassDefinition(this Type type)
{
var properties = type.GetFields();
var sb = new StringBuilder();
var classtext = @"private class $name
{
$props}";
foreach (var p in GetTypeInfo(type))
{
sb.AppendFormat(" public {0} {1} ", p.Item2, p.Item1).AppendLine(" { get; set; }");
}
return classtext.Replace("$name", type.Name).Replace("$props", sb.ToString());
}
#region Private Methods
private static List<Tuple<string, string>> GetTypeInfo(Type type)
{
var ret = new List<Tuple<string, string>>();
var fields = type.GetFields();
var props = type.GetProperties();
foreach(var p in props) ret.Add(new Tuple<string, string>(p.Name, TranslateType(p.PropertyType)));
foreach(var f in fields) ret.Add(new Tuple<string, string>(f.Name, TranslateType(f.FieldType)));
return ret;
}
private static string TranslateType(Type input)
{
string ret;
if (Nullable.GetUnderlyingType(input) != null)
{
ret = string.Format("{0}?", TranslateType(Nullable.GetUnderlyingType(input)));
}
else
{
switch (input.Name)
{
case "Int32": ret = "int"; break;
case "Int64": ret = "long"; break;
case "IntPtr": ret = "long"; break;
case "Boolean": ret = "bool"; break;
case "String":
case "Char":
case "Decimal":
ret = input.Name.ToLower(); break;
default: ret = input.Name; break;
}
}
return ret;
}
#endregion
}
使用示例:
Process.GetProcesses().First().GetType().GenerateClassDefinition();
如果使用linqpad会变得更加方便:
Process.GetProcesses().First().GetType().GenerateClassDefinition().Dump();
答案 136 :(得分:0)
Smalltalk style if/else in c#.
根据您使用的任何许可,随意将其放在codeplex上
using System;
namespace SmalltalkBooleanExtensionMethods
{
public static class BooleanExtension
{
public static T ifTrue<T> (this bool aBoolean, Func<T> method)
{
if (aBoolean)
return (T)method();
else
return default(T);
}
public static void ifTrue (this bool aBoolean, Action method)
{
if (aBoolean)
method();
}
public static T ifFalse<T> (this bool aBoolean, Func<T> method)
{
if (!aBoolean)
return (T)method();
else
return default(T);
}
public static void ifFalse (this bool aBoolean, Action method)
{
if (!aBoolean)
method();
}
public static T ifTrueifFalse<T> (this Boolean aBoolean, Func<T> methodA, Func<T> methodB)
{
if (aBoolean)
return (T)methodA();
else
return (T)methodB();
}
public static void ifTrueifFalse (this Boolean aBoolean, Action methodA, Action methodB)
{
if (aBoolean)
methodA();
else
methodB();
}
}
}
你可能已经有了一个timesRepeat方法,但它在那里。
using System;
namespace SmalltalkBooleanExtensionMethods
{
public static class IntExtension
{
public static int timesRepeat<T>(this int x, Func<T> method)
{
for (int i = x; i > 0; i--)
{
method();
}
return x;
}
public static int timesRepeat(this int x, Action method)
{
for (int i = x; i > 0; i--)
{
method();
}
return x;
}
}
}
Nunit Tests
using System;
using SmalltalkBooleanExtensionMethods;
using NUnit.Framework;
namespace SmalltalkBooleanExtensionMethodsTest
{
[TestFixture]
public class SBEMTest
{
int i;
bool itWorks;
[SetUp]
public void Init()
{
i = 0;
itWorks = false;
}
[Test()]
public void TestifTrue()
{
itWorks = (true.ifTrue(() => true));
Assert.IsTrue(itWorks);
}
[Test()]
public void TestifFalse()
{
itWorks = (false.ifFalse(() => true));
Assert.IsTrue(itWorks);
}
[Test()]
public void TestifTrueifFalse()
{
itWorks = false.ifTrueifFalse(() => false, () => true);
Assert.IsTrue(itWorks);
itWorks = false;
itWorks = true.ifTrueifFalse(() => true, () => false);
Assert.IsTrue(itWorks);
}
[Test()]
public void TestTimesRepeat()
{
(5).timesRepeat(() => i = i + 1);
Assert.AreEqual(i, 5);
}
[Test()]
public void TestVoidMethodIfTrue()
{
true.ifTrue(() => SetItWorksBooleanToTrue());
Assert.IsTrue(itWorks);
}
[Test()]
public void TestVoidMethodIfFalse()
{
false.ifFalse(() => SetItWorksBooleanToTrue());
Assert.IsTrue(itWorks);
}
public void TestVoidMethodIfTrueIfFalse()
{
true.ifTrueifFalse(() => SetItWorksBooleanToTrue(), () => SetItWorksBooleanToFalse());
false.ifTrueifFalse(() => SetItWorksBooleanToFalse(), () => SetItWorksBooleanToTrue());
Assert.IsTrue(itWorks);
}
public void TestVoidMethodTimesRepeat()
{
(5).timesRepeat(() => AddOneToi());
Assert.AreEqual(i, 5);
}
public void SetItWorksBooleanToTrue()
{
itWorks = true;
}
public void SetItWorksBooleanToFalse()
{
itWorks = false;
}
public void AddOneToi()
{
i = i + 1;
}
}
}
答案 137 :(得分:0)
我已经创建了一个扩展方法来选择ASP.NET中下拉列表中的项目。
以下是代码
public static class Utilities
{
public enum DropDownListSelectionType
{
ByValue,
ByText
}
public static void SelectItem(this System.Web.UI.WebControls.DropDownList drp, string selectedValue, DropDownListSelectionType type)
{
drp.ClearSelection();
System.Web.UI.WebControls.ListItem li;
if (type == DropDownListSelectionType.ByValue)
li = drp.Items.FindByValue(selectedValue.Trim());
else
li = drp.Items.FindByText(selectedValue.Trim());
if (li != null)
li.Selected = true;
}}
可以通过以下代码行调用此方法,以便按文本
进行选择DropDownList1.SelectItem("ABCD", Utilities.DropDownListSelectionType.ByText);
或按值选择
DropDownList1.SelectItem("11", Utilities.DropDownListSelectionType.ByValue);
如果无法找到传入的文本/值,上面的代码就不会选择任何内容。
答案 138 :(得分:0)
这是我经常使用的控制调用扩展程序;
public static class InvokeExtensions
{
public static void InvokeHandler(this Control control, MethodInvoker del) // Sync. control-invoke extension.
{
if (control.InvokeRequired)
{
control.Invoke(del);
return;
}
del(); // run the actual code.
}
public static void AsyncInvokeHandler(this Control control, MethodInvoker del) // Async. control-invoke extension.
{
if (control.InvokeRequired)
{
control.BeginInvoke(del);
return;
}
del(); // run the actual code.
}
}
样品;
this.TreeView.AsyncInvokeHandler(() =>
{
this.Text = 'xyz'
});
允许跨线程gui-updates。
答案 139 :(得分:0)
比较两个对象的相等性,而不必(必须)覆盖Equals或实现IEquatable&lt;&gt;。
你为什么要这样做?当你真的想知道两个对象是否相等时,你却懒得覆盖Equals(object)
或实现IEquatable<T>
。或者,更现实地说,如果你有一个非常复杂的类并且手动实现Equals将是非常乏味,容易出错,并且维护起来并不好玩。如果你不太在乎性能,它也会有所帮助。
我目前正在使用IsEqualTo
,因为第二个原因 - 我有一个具有许多属性的类,其类型是其他用户定义的类,每个类都有许多其他属性,其类型是其他用户定义的类,无限的。在许多这些类中加入一堆集合,实现Equals(object)
真的变成了一场噩梦。
用法:
if (myTerriblyComplexObject.IsEqualTo(myOtherTerriblyComplexObject))
{
// Do something terribly interesting.
}
为了确定平等,我进行了大量的比较。我尽一切努力以“正确”的顺序做“正确的”。比较依次是:
Equals(object, object)
方法。如果返回true,则返回true。如果引用相同,它将返回true。如果thisObject
覆盖Equals(object)
。thisObject
为null,则返回false。如果它为空,则不能进行进一步的比较。thisObject
已覆盖Equals(object)
,则返回false。由于它会覆盖Equals,因此必须表示Equals在步骤#1执行并返回false。如果有人打扰覆盖Equals,我们应该尊重并返回Equals返回的内容。thisObject
继承自IEquatable<T>
,otherObject
可以分配到T
,请使用反射获取Equals(T)
方法。调用该方法并返回其返回值。IEnumerable
,则返回是否包含相同的项目,使用相同的顺序,使用IsEqualTo来比较项目。thisObject
没有Equals方法,那么没有办法真实地评估两个不同类型的对象是真的。Equals(object)
测试 - 足够说了。thisObject
的每个属性,使用IsEqualTo测试其值。如果有任何返回false,则返回false。如果全部返回true,则返回true。字符串比较可能更好,但易于实现。另外,我并非100%确定我正在处理结构。
不用多说,这是扩展方法:
/// <summary>
/// Provides extension methods to determine if objects are equal.
/// </summary>
public static class EqualsEx
{
/// <summary>
/// The <see cref="Type"/> of <see cref="string"/>.
/// </summary>
private static readonly Type StringType = typeof(string);
/// <summary>
/// The <see cref="Type"/> of <see cref="object"/>.
/// </summary>
private static readonly Type ObjectType = typeof(object);
/// <summary>
/// The <see cref="Type"/> of <see cref="IEquatable{T}"/>.
/// </summary>
private static readonly Type EquatableType = typeof(IEquatable<>);
/// <summary>
/// Determines whether <paramref name="thisObject"/> is equal to <paramref name="otherObject"/>.
/// </summary>
/// <param name="thisObject">
/// This object.
/// </param>
/// <param name="otherObject">
/// The other object.
/// </param>
/// <returns>
/// True, if they are equal, otherwise false.
/// </returns>
public static bool IsEqualTo(this object thisObject, object otherObject)
{
if (Equals(thisObject, otherObject))
{
// Always check Equals first. If the object has overridden Equals, use it. This will also capture the case where both are the same reference.
return true;
}
if (thisObject == null)
{
// Because Equals(object, object) returns true if both are null, if either is null, return false.
return false;
}
var thisObjectType = thisObject.GetType();
var equalsMethod = thisObjectType.GetMethod("Equals", BindingFlags.Public | BindingFlags.Instance, null, new[] { ObjectType }, null);
if (equalsMethod.DeclaringType == thisObjectType)
{
// thisObject overrides Equals, and we have already failed the Equals test, so return false.
return false;
}
var otherObjectType = otherObject == null ? null : otherObject.GetType();
// If thisObject inherits from IEquatable<>, and otherObject can be passed into its Equals method, use it.
var equatableTypes = thisObjectType.GetInterfaces().Where( // Get interfaces of thisObjectType that...
i => i.IsGenericType // ...are generic...
&& i.GetGenericTypeDefinition() == EquatableType // ...and are IEquatable of some type...
&& (otherObjectType == null || i.GetGenericArguments()[0].IsAssignableFrom(otherObjectType))); // ...and otherObjectType can be assigned to the IEquatable's type.
if (equatableTypes.Any())
{
// If we found any interfaces that meed our criteria, invoke the Equals method for each interface.
// If any return true, return true. If all return false, return false.
return equatableTypes
.Select(equatableType => equatableType.GetMethod("Equals", BindingFlags.Public | BindingFlags.Instance))
.Any(equatableEqualsMethod => (bool)equatableEqualsMethod.Invoke(thisObject, new[] { otherObject }));
}
if (thisObjectType != StringType && thisObject is IEnumerable && otherObject is IEnumerable)
{
// If both are IEnumerable, check their items.
var thisEnumerable = ((IEnumerable)thisObject).Cast<object>();
var otherEnumerable = ((IEnumerable)otherObject).Cast<object>();
return thisEnumerable.SequenceEqual(otherEnumerable, IsEqualToComparer.Instance);
}
if (thisObjectType != otherObjectType)
{
// If they have different types, they cannot be equal.
return false;
}
if (thisObjectType.IsValueType || thisObjectType == StringType)
{
// If it is a value type, we have already determined that they are not equal, so return false.
return false;
}
// Recurse into each public property: if any are not equal, return false. If all are true, return true.
return !(from propertyInfo in thisObjectType.GetProperties()
let thisPropertyValue = propertyInfo.GetValue(thisObject, null)
let otherPropertyValue = propertyInfo.GetValue(otherObject, null)
where !thisPropertyValue.IsEqualTo(otherPropertyValue)
select thisPropertyValue).Any();
}
/// <summary>
/// A <see cref="IEqualityComparer{T}"/> to be used when comparing sequences of collections.
/// </summary>
private class IsEqualToComparer : IEqualityComparer<object>
{
/// <summary>
/// The singleton instance of <see cref="IsEqualToComparer"/>.
/// </summary>
public static readonly IsEqualToComparer Instance;
/// <summary>
/// Initializes static members of the <see cref="EqualsEx.IsEqualToComparer"/> class.
/// </summary>
static IsEqualToComparer()
{
Instance = new IsEqualToComparer();
}
/// <summary>
/// Prevents a default instance of the <see cref="EqualsEx.IsEqualToComparer"/> class from being created.
/// </summary>
private IsEqualToComparer()
{
}
/// <summary>
/// Determines whether the specified objects are equal.
/// </summary>
/// <param name="x">
/// The first object to compare.
/// </param>
/// <param name="y">
/// The second object to compare.
/// </param>
/// <returns>
/// true if the specified objects are equal; otherwise, false.
/// </returns>
bool IEqualityComparer<object>.Equals(object x, object y)
{
return x.IsEqualTo(y);
}
/// <summary>
/// Not implemented - throws an <see cref="NotImplementedException"/>.
/// </summary>
/// <param name="obj">
/// The <see cref="object"/> for which a hash code is to be returned.
/// </param>
/// <returns>
/// A hash code for the specified object.
/// </returns>
int IEqualityComparer<object>.GetHashCode(object obj)
{
throw new NotImplementedException();
}
}
}
答案 140 :(得分:0)
Sql server有~2000个参数的限制,如果你有10k ID并想要与它们连接的记录,这是一个痛苦。我编写了这些接受批量的id列表的方法,并按如下方式调用:
List<Order> orders = dataContext.Orders.FetchByIds(
orderIdChunks,
list => row => list.Contains(row.OrderId)
);
List<Customer> customers = dataContext.Orders.FetchByIds(
orderIdChunks,
list => row => list.Contains(row.OrderId),
row => row.Customer
);
public static List<ResultType> FetchByIds<RecordType, ResultType>(
this IQueryable<RecordType> querySource,
List<List<int>> IdChunks,
Func<List<int>, Expression<Func<RecordType, bool>>> filterExpressionGenerator,
Expression<Func<RecordType, ResultType>> projectionExpression
) where RecordType : class
{
List<ResultType> result = new List<ResultType>();
foreach (List<int> chunk in IdChunks)
{
Expression<Func<RecordType, bool>> filterExpression =
filterExpressionGenerator(chunk);
IQueryable<ResultType> query = querySource
.Where(filterExpression)
.Select(projectionExpression);
List<ResultType> rows = query.ToList();
result.AddRange(rows);
}
return result;
}
public static List<RecordType> FetchByIds<RecordType>(
this IQueryable<RecordType> querySource,
List<List<int>> IdChunks,
Func<List<int>, Expression<Func<RecordType, bool>>> filterExpressionGenerator
) where RecordType : class
{
Expression<Func<RecordType, RecordType>> identity = r => r;
return FetchByIds(
querySource,
IdChunks,
filterExpressionGenerator,
identity
);
}
答案 141 :(得分:0)
我们有一个可在环境之间部署的部署工具。由于文件可以标记为已修改但实际上没有不同,我想出了这个:
/// <summary>
/// Compares the files to see if they are different.
/// First checks file size
/// Then modified if the file is larger than the specified size
/// Then compares the bytes
/// </summary>
/// <param name="file1">The source file</param>
/// <param name="file2">The destination file</param>
/// <param name="mb">Skip the smart check if the file is larger than this many megabytes. Default is 10.</param>
/// <returns></returns>
public static bool IsDifferentThan(this FileInfo file1, FileInfo file2, int mb = 10)
{
var ret = false;
// different size is a different file
if(file1.Length != file2.Length) return true;
// if the file times are different and the file is bigger than 10mb flag it for updating
if(file1.LastWriteTimeUtc > file2.LastWriteTimeUtc && file1.Length > ((mb*1024)*1024)) return true;
var f1 = File.ReadAllBytes(file1.FullName);
var f2 = File.ReadAllBytes(file2.FullName);
// loop through backwards because if they are different
// it is more likely that the last few bytes will be different
// than the first few
for(var i = file1.Length - 1; i > 0; i--)
{
if(f1[i] != f2[i])
{
ret = true;
break;
}
}
return ret;
}
答案 142 :(得分:0)
如果你有波斯语,必须用波斯语向用户显示数字:
static public string ToFaString (this string value)
{
// 1728 , 1584
string result = "";
if (value != null)
{
char[] resChar = value.ToCharArray();
for (int i = 0; i < resChar.Length; i++)
{
if (resChar[i] >= '0' && resChar[i] <= '9')
result += (char)(resChar[i] + 1728);
else
result += resChar[i];
}
}
return result;
}
答案 143 :(得分:0)
如果你需要检查你的字符串Is Is char是0:
static public bool IsAllZero (this string input)
{
if(string.IsNullOrEmpty(input))
return true;
foreach (char ch in input)
{
if(ch != '0')
return false;
}
return true;
}
答案 144 :(得分:0)
关于序列化和配置,最好使用long作为DateTime,所以:
public static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0);
public static long ToUnixTimestamp(this DateTime dateTime)
{
return (long) (dateTime - Epoch).TotalSeconds;
}
public static long ToUnixUltraTimestamp(this DateTime dateTime)
{
return (long) (dateTime - Epoch).TotalMilliseconds;
}
和向后
public static DateTime ToDateTime(this long unixDateTime)
{
return Epoch.AddSeconds(unixDateTime);
}
public static DateTime ToDateTimeUltra(this long unixUltraDateTime)
{
return Epoch.AddMilliseconds(unixUltraDateTime);
}
答案 145 :(得分:0)
我使用以下扩展来扩展所有集合(也许有人发现这些有用):
/// <summary>
/// Collection Helper
/// </summary>
/// <remarks>
/// Use IEnumerable by default, but when altering or getting item at index use IList.
/// </remarks>
public static class CollectionHelper
{
#region Alter;
/// <summary>
/// Swap item to another place
/// </summary>
/// <typeparam name="T">Collection type</typeparam>
/// <param name="this">Collection</param>
/// <param name="IndexA">Index a</param>
/// <param name="IndexB">Index b</param>
/// <returns>New collection</returns>
public static IList<T> Swap<T>(this IList<T> @this, Int32 IndexA, Int32 IndexB)
{
T Temp = @this[IndexA];
@this[IndexA] = @this[IndexB];
@this[IndexB] = Temp;
return @this;
}
/// <summary>
/// Swap item to the left
/// </summary>
/// <typeparam name="T">Collection type</typeparam>
/// <param name="this">Collection</param>
/// <param name="Index">Index</param>
/// <returns>New collection</returns>
public static IList<T> SwapLeft<T>(this IList<T> @this, Int32 Index)
{
return @this.Swap(Index, Index - 1);
}
/// <summary>
/// Swap item to the right
/// </summary>
/// <typeparam name="T">Collection type</typeparam>
/// <param name="this">Collection</param>
/// <param name="Index">Index</param>
/// <returns>New collection</returns>
public static IList<T> SwapRight<T>(this IList<T> @this, Int32 Index)
{
return @this.Swap(Index, Index + 1);
}
#endregion Alter;
#region Action;
/// <summary>
/// Execute action at specified index
/// </summary>
/// <typeparam name="T">Collection type</typeparam>
/// <param name="this">Collection</param>
/// <param name="Index">Index</param>
/// <param name="ActionAt">Action to execute</param>
/// <returns>New collection</returns>
public static IList<T> ActionAt<T>(this IList<T> @this, Int32 Index, Action<T> ActionAt)
{
ActionAt(@this[Index]);
return @this;
}
#endregion Action;
#region Randomize;
/// <summary>
/// Take random items
/// </summary>
/// <typeparam name="T">Collection type</typeparam>
/// <param name="this">Collection</param>
/// <param name="Count">Number of items to take</param>
/// <returns>New collection</returns>
public static IEnumerable<T> TakeRandom<T>(this IEnumerable<T> @this, Int32 Count)
{
return @this.Shuffle().Take(Count);
}
/// <summary>
/// Take random item
/// </summary>
/// <typeparam name="T">Collection type</typeparam>
/// <param name="this">Collection</param>
/// <returns>Item</returns>
public static T TakeRandom<T>(this IEnumerable<T> @this)
{
return @this.TakeRandom(1).Single();
}
/// <summary>
/// Shuffle list
/// </summary>
/// <typeparam name="T">Collection type</typeparam>
/// <param name="this">Collection</param>
/// <returns>New collection</returns>
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> @this)
{
return @this.OrderBy(Item => Guid.NewGuid());
}
#endregion Randomize;
#region Navigate;
/// <summary>
/// Get next item in collection and give first item, when last item is selected;
/// </summary>
/// <typeparam name="T">Collection type</typeparam>
/// <param name="this">Collection</param>
/// <param name="Index">Index in collection</param>
/// <returns>Next item</returns>
public static T Next<T>(this IList<T> @this, ref Int32 Index)
{
Index = ++Index >= 0 && Index < @this.Count ? Index : 0;
return @this[Index];
}
/// <summary>
/// Get previous item in collection and give last item, when first item is selected;
/// </summary>
/// <typeparam name="T">Collection type</typeparam>
/// <param name="this">Collection</param>
/// <param name="Index">Index in collection</param>
/// <returns>Previous item</returns>
public static T Previous<T>(this IList<T> @this, ref Int32 Index)
{
Index = --Index >= 0 && Index < @this.Count ? Index : @this.Count - 1;
return @this[Index];
}
#endregion Navigate;
#region Clone;
/// <summary>
///
/// </summary>
/// <typeparam name="T">Collection type</typeparam>
/// <param name="this">Collection</param>
/// <returns>Cloned collection</returns>
public static IEnumerable<T> Clone<T>(this IEnumerable<T> @this) where T : ICloneable
{
return @this.Select(Item => (T)Item.Clone());
}
#endregion Clone;
#region String;
/// <summary>
/// Joins multiple string with Separator
/// </summary>
/// <param name="this">Collection</param>
/// <param name="Separator">Separator</param>
/// <returns>Joined string</returns>
public static String Join(this IEnumerable<String> @this, String Separator = "")
{
return String.Join(Separator, @this);
}
#endregion String;
}
答案 146 :(得分:0)
怎么样......
public static bool IsWinXPOrHigher(this OperatingSystem OS)
{
return (OS.Platform == PlatformID.Win32NT)
&& ((OS.Version.Major > 5) || ((OS.Version.Major == 5) && (OS.Version.Minor >= 1)));
}
public static bool IsWinVistaOrHigher(this OperatingSystem OS)
{
return (OS.Platform == PlatformID.Win32NT)
&& (OS.Version.Major >= 6);
}
public static bool IsWin7OrHigher(this OperatingSystem OS)
{
return (OS.Platform == PlatformID.Win32NT)
&& ((OS.Version.Major > 6) || ((OS.Version.Major == 6) && (OS.Version.Minor >= 1)));
}
public static bool IsWin8OrHigher(this OperatingSystem OS)
{
return (OS.Platform == PlatformID.Win32NT)
&& ((OS.Version.Major > 6) || ((OS.Version.Major == 6) && (OS.Version.Minor >= 2)));
}
用法:
if (Environment.OSVersion.IsWinXPOrHigher())
{
// do stuff
}
if (Environment.OSVersion.IsWinVistaOrHigher())
{
// do stuff
}
if (Environment.OSVersion.IsWin7OrHigher())
{
// do stuff
}
if (Environment.OSVersion.IsWin8OrHigher())
{
// do stuff
}
答案 147 :(得分:0)
另一个,这次是为了让UriBuilder在处理查询参数时更加友好。
/// <summary>
/// Adds the specified query parameter to the URI builder.
/// </summary>
/// <param name="builder">The builder.</param>
/// <param name="parameterName">Name of the parameter.</param>
/// <param name="value">The URI escaped value.</param>
/// <returns>The final full query string.</returns>
public static string AddQueryParam(this UriBuilder builder, string parameterName, string value)
{
if (parameterName == null)
throw new ArgumentNullException("parameterName");
if (parameterName.Length == 0)
throw new ArgumentException("The parameter name is empty.");
if (value == null)
throw new ArgumentNullException("value");
if (value.Length == 0)
throw new ArgumentException("The value is empty.");
if (builder.Query.Length == 0)
{
builder.Query = String.Concat(parameterName, "=", value);
}
else if
(builder.Query.Contains(String.Concat("&", parameterName, "="))
|| builder.Query.Contains(String.Concat("?", parameterName, "=")))
{
throw new InvalidOperationException(String.Format("The parameter {0} already exists.", parameterName));
}
else
{
builder.Query = String.Concat(builder.Query.Substring(1), "&", parameterName, "=", value);
}
return builder.Query;
}
答案 148 :(得分:-3)
获取URI的根域。
/// <summary>Gets the root domain of any URI</summary>
/// <param name="uri">URI to get root domain of</param>
/// <returns>Root domain with TLD</returns>
public static string GetRootDomain(this System.Uri uri)
{
if (uri == null)
return null;
string Domain = uri.Host;
while (System.Text.RegularExpressions.Regex.Matches(Domain, @"[\.]").Count > 1)
Domain = Domain.Substring(Domain.IndexOf('.') + 1);
Domain = Domain.Substring(0, Domain.IndexOf('.'));
return Domain;
}
答案 149 :(得分:-13)
轻松地将对象序列化为XML:
public static string ToXml<T>(this T obj) where T : class
{
XmlSerializer s = new XmlSerializer(obj.GetType());
using (StringWriter writer = new StringWriter())
{
s.Serialize(writer, obj);
return writer.ToString();
}
}
"<root><child>foo</child</root>".ToXml<MyCustomType>();