我开始非常喜欢延伸方法...我想知道是否有人偶然发现了一个真正引起他们注意的人,或者只是发现了聪明。
我今天写的一个例子:
由于其他用户的评论而被编辑:
public static IEnumerable<int> To(this int fromNumber, int toNumber) {
while (fromNumber < toNumber) {
yield return fromNumber;
fromNumber++;
}
}
这允许将for循环写为foreach循环:
foreach (int x in 0.To(16)) {
Console.WriteLine(Math.Pow(2, x).ToString());
}
我迫不及待想看其他例子!享受!
答案 0 :(得分:18)
完整的解决方案太大而无法放在这里,但我写了一系列扩展方法,可以让您轻松地将DataTable转换为CSV。
public static String ToCSV(this DataTable dataTable)
{
return dataTable.ToCSV(null, COMMA, true);
}
public static String ToCSV(this DataTable dataTable, String qualifier)
{
return dataTable.ToCSV(qualifier, COMMA, true);
}
private static String ToCSV(this DataTable dataTable, String qualifier, String delimiter, Boolean includeColumnNames)
{
if (dataTable == null) return null;
if (qualifier == delimiter)
{
throw new InvalidOperationException(
"The qualifier and the delimiter are identical. This will cause the CSV to have collisions that might result in data being parsed incorrectly by another program.");
}
var sbCSV = new StringBuilder();
var delimiterToUse = delimiter ?? COMMA;
if (includeColumnNames)
sbCSV.AppendLine(dataTable.Columns.GetHeaderLine(qualifier, delimiterToUse));
foreach (DataRow row in dataTable.Rows)
{
sbCSV.AppendLine(row.ToCSVLine(qualifier, delimiterToUse));
}
return sbCSV.Length > 0 ? sbCSV.ToString() : null;
}
private static String ToCSVLine(this DataRow dataRow, String qualifier, String delimiter)
{
var colCount = dataRow.Table.Columns.Count;
var rowValues = new String[colCount];
for (var i = 0; i < colCount; i++)
{
rowValues[i] = dataRow[i].Qualify(qualifier);
}
return String.Join(delimiter, rowValues);
}
private static String GetHeaderLine(this DataColumnCollection columns, String qualifier, String delimiter)
{
var colCount = columns.Count;
var colNames = new String[colCount];
for (var i = 0; i < colCount; i++)
{
colNames[i] = columns[i].ColumnName.Qualify(qualifier);
}
return String.Join(delimiter, colNames);
}
private static String Qualify(this Object target, String qualifier)
{
return qualifier + target + qualifier;
}
在一天结束时,您可以这样称呼它:
someDataTable.ToCSV(); //Plain old CSV
someDataTable.ToCSV("\""); //Double quote qualifier
someDataTable.ToCSV("\"", "\t"); //Tab delimited
答案 1 :(得分:18)
这是最近一直在玩我的游戏:
public static IDisposable Tag(this HtmlHelper html, string tagName)
{
if (html == null)
throw new ArgumentNullException("html");
Action<string> a = tag => html.Write(String.Format(tag, tagName));
a("<{0}>");
return new Memento(() => a("</{0}>"));
}
用过:
using (Html.Tag("ul"))
{
this.Model.ForEach(item => using(Html.Tag("li")) Html.Write(item));
using(Html.Tag("li")) Html.Write("new");
}
Memento是一个方便的课程:
public sealed class Memento : IDisposable
{
private bool Disposed { get; set; }
private Action Action { get; set; }
public Memento(Action action)
{
if (action == null)
throw new ArgumentNullException("action");
Action = action;
}
void IDisposable.Dispose()
{
if (Disposed)
throw new ObjectDisposedException("Memento");
Disposed = true;
Action();
}
}
并完成依赖项:
public static void Write(this HtmlHelper html, string content)
{
if (html == null)
throw new ArgumentNullException("html");
html.ViewContext.HttpContext.Response.Write(content);
}
答案 2 :(得分:13)
我不是INotifyPropertyChanged
接口的粉丝,要求将属性名称作为字符串传递。我想要一种强类型的方法在编译时检查我只是为现有的属性提出并处理属性更改。我使用这段代码来做到这一点:
public static class INotifyPropertyChangedExtensions
{
public static string ToPropertyName<T>(this Expression<Func<T>> @this)
{
var @return = string.Empty;
if (@this != null)
{
var memberExpression = @this.Body as MemberExpression;
if (memberExpression != null)
{
@return = memberExpression.Member.Name;
}
}
return @return;
}
}
在实现INotifyPropertyChanged
的类中,我包含了这个帮助方法:
protected void NotifySetProperty<T>(ref T field, T value,
Expression<Func<T>> propertyExpression)
{
if (field == null ? value != null : !field.Equals(value))
{
field = value;
this.NotifyPropertyChanged(propertyExpression.ToPropertyName());
}
}
所以最后我可以做这件事:
private string _name;
public string Name
{
get { return _name; }
set { this.NotifySetProperty(ref _name, value, () => this.Name); }
}
它是强类型的,我只为实际改变其值的属性引发事件。
答案 3 :(得分:12)
这不是很聪明,但我修改了---- OrDefault方法,因此您可以指定内联的默认项,而不是在代码中稍后检查null:
public static T SingleOrDefault<T> ( this IEnumerable<T> source,
Func<T, bool> action, T theDefault )
{
T item = source.SingleOrDefault<T>(action);
if (item != null)
return item;
return theDefault;
}
它令人难以置信的简单,但真的有助于清理那些空检查。当您的UI期望X项目列表(如锦标赛系统或游戏玩家插槽)并且您希望显示“空座位”时,最佳使用。
用法:
return jediList.SingleOrDefault(
j => j.LightsaberColor == "Orange",
new Jedi() { LightsaberColor = "Orange", Name = "DarthNobody");
答案 4 :(得分:11)
这是我一起砍的一个,所以随意挑选它。它采用(有序)整数列表并返回连续范围的字符串列表。例如:
1,2,3,7,10,11,12 --> "1-3","7","10-12"
该函数(在静态类中):
public static IEnumerable<string> IntRanges(this IEnumerable<int> numbers)
{
int rangeStart = 0;
int previous = 0;
if (!numbers.Any())
yield break;
rangeStart = previous = numbers.FirstOrDefault();
foreach (int n in numbers.Skip(1))
{
if (n - previous > 1) // sequence break - yield a sequence
{
if (previous > rangeStart)
{
yield return string.Format("{0}-{1}", rangeStart, previous);
}
else
{
yield return rangeStart.ToString();
}
rangeStart = n;
}
previous = n;
}
if (previous > rangeStart)
{
yield return string.Format("{0}-{1}", rangeStart, previous);
}
else
{
yield return rangeStart.ToString();
}
}
用法示例:
this.WeekDescription = string.Join(",", from.WeekPattern.WeekPatternToInts().IntRanges().ToArray());
此代码用于转换DailyWTF值得的时间表应用程序中的数据。 WeekPattern是存储在字符串“0011011100 ...”中的位掩码。 WeekPatternToInts()将其转换为IEnumerable&lt; int&gt;,在这种情况下为[3,4,6,7,8],变为“3-4,6-8”。它为用户提供了讲座发生在学术周范围内的简洁描述。
答案 5 :(得分:11)
我想使用的两个是InsertWhere <T
&gt;和RemoveWhere <T
&gt;我写的扩展方法。在WPF和Silverlight中使用ObservableCollections我经常需要修改有序列表而不重新创建它们。这些方法允许我根据提供的Func插入和删除,因此.OrderBy()不需要重新调用。
/// <summary>
/// Removes all items from the provided <paramref name="list"/> that match the<paramref name="predicate"/> expression.
/// </summary>
/// <typeparam name="T">The class type of the list items.</typeparam>
/// <param name="list">The list to remove items from.</param>
/// <param name="predicate">The predicate expression to test against.</param>
public static void RemoveWhere<T>(this IList<T> list, Func<T, bool> predicate)
{
T[] copy = new T[] { };
Array.Resize(ref copy, list.Count);
list.CopyTo(copy, 0);
for (int i = copy.Length - 1; i >= 0; i--)
{
if (predicate(copy[i]))
{
list.RemoveAt(i);
}
}
}
/// <summary>
/// Inserts an Item into a list at the first place that the <paramref name="predicate"/> expression fails. If it is true in all cases, then the item is appended to the end of the list.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <param name="obj"></param>
/// <param name="predicate">The sepcified function that determines when the <paramref name="obj"/> should be added. </param>
public static void InsertWhere<T>(this IList<T> list, T obj, Func<T, bool> predicate)
{
for (int i = 0; i < list.Count; i++)
{
// When the function first fails it inserts the obj paramiter.
// For example, in a list myList of ordered Int32's {1,2,3,4,5,10,12}
// Calling myList.InsertWhere( 8, x => 8 > x) inserts 8 once the list item becomes greater then or equal to it.
if(!predicate(list[i]))
{
list.Insert(i, obj);
return;
}
}
list.Add(obj);
}
修改强>
Talljoe对RemoveWhere / RemoveAll进行了一些重大改进,这是我匆忙构建的。每三个项目删除大约3个项目,新版本只需要约50毫秒(如果它可以调用List.RemoveAll,则少于10个!)而不是RemoveWhere的多秒钟(我厌倦了等待它。)
这是他大大改进的版本,再次感谢!
public static void RemoveAll<T>(this IList<T> instance, Predicate<T> predicate)
{
if (instance == null)
throw new ArgumentNullException("instance");
if (predicate == null)
throw new ArgumentNullException("predicate");
if (instance is T[])
throw new NotSupportedException();
var list = instance as List<T>;
if (list != null)
{
list.RemoveAll(predicate);
return;
}
int writeIndex = 0;
for (int readIndex = 0; readIndex < instance.Count; readIndex++)
{
var item = instance[readIndex];
if (predicate(item)) continue;
if (readIndex != writeIndex)
{
instance[writeIndex] = item;
}
++writeIndex;
}
if (writeIndex != instance.Count)
{
for (int deleteIndex = instance.Count - 1; deleteIndex >= writeIndex; --deleteIndex)
{
instance.RemoveAt(deleteIndex);
}
}
}
答案 6 :(得分:10)
我有各种.Debugify
扩展方法,可用于将对象转储到日志文件中。例如,这是我的字典调试(我有List,Datatable,param数组等):
public static string Debugify<TKey, TValue>(this Dictionary<TKey, TValue> dictionary) {
string Result = "";
if (dictionary.Count > 0) {
StringBuilder ResultBuilder = new StringBuilder();
int Counter = 0;
foreach (KeyValuePair<TKey, TValue> Entry in dictionary) {
Counter++;
ResultBuilder.AppendFormat("{0}: {1}, ", Entry.Key, Entry.Value);
if (Counter % 10 == 0) ResultBuilder.AppendLine();
}
Result = ResultBuilder.ToString();
}
return Result;
}
这里有一个DbParameterCollection(用于转储对日志文件的数据库调用):
public static string Debugify(this DbParameterCollection parameters) {
List<string> ParameterValuesList = new List<string>();
foreach (DbParameter Parameter in parameters) {
string ParameterName, ParameterValue;
ParameterName = Parameter.ParameterName;
if (Parameter.Direction == ParameterDirection.ReturnValue)
continue;
if (Parameter.Value == null || Parameter.Value.Equals(DBNull.Value))
ParameterValue = "NULL";
else
{
switch (Parameter.DbType)
{
case DbType.String:
case DbType.Date:
case DbType.DateTime:
case DbType.Guid:
case DbType.Xml:
ParameterValue
= "'" + Parameter
.Value
.ToString()
.Replace(Environment.NewLine, "")
.Left(80, "...") + "'"; // Left... is another nice one
break;
default:
ParameterValue = Parameter.Value.ToString();
break;
}
if (Parameter.Direction != ParameterDirection.Input)
ParameterValue += " " + Parameter.Direction.ToString();
}
ParameterValuesList.Add(string.Format("{0}={1}", ParameterName, ParameterValue));
}
return string.Join(", ", ParameterValuesList.ToArray());
}
示例结果:
Log.DebugFormat("EXEC {0} {1}", procName, params.Debugify);
// EXEC spProcedure @intID=5, @nvName='Michael Haren', @intRefID=11 OUTPUT
请注意,如果在数据库调用之后调用此,您也将获得输出参数。我在包含SP名称的行上调用它,这样我就可以将调用复制/粘贴到SSMS中进行调试。
这些使我的日志文件非常容易生成而不会中断我的代码。
答案 7 :(得分:9)
一对扩展方法,用于将base-36字符串(!)转换为整数:
public static int ToBase10(this string base36)
{
if (string.IsNullOrEmpty(base36))
return 0;
int value = 0;
foreach (var c in base36.Trim())
{
value = value * 36 + c.ToBase10();
}
return value;
}
public static int ToBase10(this char c)
{
if (c >= '0' && c <= '9')
return c - '0';
c = char.ToUpper(c);
if (c >= 'A' && c <= 'Z')
return c - 'A' + 10;
return 0;
}
(有些天才认为在数据库中存储数字的最佳方法是将它们编码为字符串。小数点占用太多空间。十六进制更好,但不使用字符GZ。所以很明显你将base-16扩展到base -36!)
答案 8 :(得分:7)
我编写了一系列扩展方法,以便更容易操作ADO.NET对象和方法:
在一条指令中从DbConnection创建一个DbCommand:
public static DbCommand CreateCommand(this DbConnection connection, string commandText)
{
DbCommand command = connection.CreateCommand();
command.CommandText = commandText;
return command;
}
向DbCommand添加参数:
public static DbParameter AddParameter(this DbCommand command, string name, DbType dbType)
{
DbParameter p = AddParameter(command, name, dbType, 0, ParameterDirection.Input);
return p;
}
public static DbParameter AddParameter(this DbCommand command, string name, DbType dbType, object value)
{
DbParameter p = AddParameter(command, name, dbType, 0, ParameterDirection.Input);
p.Value = value;
return p;
}
public static DbParameter AddParameter(this DbCommand command, string name, DbType dbType, int size)
{
return AddParameter(command, name, dbType, size, ParameterDirection.Input);
}
public static DbParameter AddParameter(this DbCommand command, string name, DbType dbType, int size, ParameterDirection direction)
{
DbParameter parameter = command.CreateParameter();
parameter.ParameterName = name;
parameter.DbType = dbType;
parameter.Direction = direction;
parameter.Size = size;
command.Parameters.Add(parameter);
return parameter;
}
按名称而不是索引访问DbDataReader字段:
public static DateTime GetDateTime(this DbDataReader reader, string name)
{
int i = reader.GetOrdinal(name);
return reader.GetDateTime(i);
}
public static decimal GetDecimal(this DbDataReader reader, string name)
{
int i = reader.GetOrdinal(name);
return reader.GetDecimal(i);
}
public static double GetDouble(this DbDataReader reader, string name)
{
int i = reader.GetOrdinal(name);
return reader.GetDouble(i);
}
public static string GetString(this DbDataReader reader, string name)
{
int i = reader.GetOrdinal(name);
return reader.GetString(i);
}
...
另一个(不相关的)扩展方法允许我在WinForms表单和控件see here上执行DragMove操作(如在WPF中)。
答案 9 :(得分:5)
虽然非常简单,但我发现这个特别有用,因为我从一个完整的结果集中获得了一百万次项目的页面:
public static class QueryableExtensions
{
public static IQueryable<T> Page(this IQueryable<T> query, int pageNumber, int pageSize)
{
int skipCount = (pageNumber-1) * pageSize;
query = query.Skip(skipCount);
query = query.Take(pageSize);
return query;
}
}
答案 10 :(得分:5)
通常,我需要根据Enum值显示用户友好的值,但不想使用自定义属性路由,因为它看起来不太优雅。
使用这个方便的扩展方法:
public static string EnumValue(this MyEnum e) {
switch (e) {
case MyEnum.First:
return "First Friendly Value";
case MyEnum.Second:
return "Second Friendly Value";
case MyEnum.Third:
return "Third Friendly Value";
}
return "Horrible Failure!!";
}
我可以这样做:
Console.WriteLine(MyEnum.First.EnumValue());
耶!
答案 11 :(得分:5)
这是一种在引发事件之前集中空检查的扩展方法。
public static class EventExtension
{
public static void RaiseEvent<T>(this EventHandler<T> handler, object obj, T args) where T : EventArgs
{
EventHandler<T> theHandler = handler;
if (theHandler != null)
{
theHandler(obj, args);
}
}
}
答案 12 :(得分:5)
我在这里看到的大多数扩展方法示例都违反了最佳做法。 扩展方法功能强大,但应谨慎使用。根据我的经验,具有旧式语法的静态助手/实用程序类通常对大多数这些都是首选。
对于Enums的扩展方法,有一些话要说,因为它们不可能有方法。如果您在与Enum相同的命名空间中定义它们并在同一个程序集中,它们将以透明方式工作。
答案 13 :(得分:3)
这个非常简单,但是我做了很多检查,所以我最终为它做了一个扩展方法。我最喜欢的扩展方法往往是像这样简单明了的扩展方法,或者像Taylor L'提升事件的扩展方法。
public static bool IsNullOrEmpty(this ICollection e)
{
return e == null || e.Count == 0;
}
答案 14 :(得分:2)
我正在将大量的Java转换为C#。许多方法仅在大小写或其他小的语法差异方面有所不同。所以Java代码如
myString.toLowerCase();
不会编译,只能添加扩展方法
public static void toLowerCase(this string s)
{
s.ToLower();
}
我可以捕获所有方法(我假设一个好的编译器会内联这个?)。
这无疑使这项工作变得更加容易和可靠。 (我感谢@Yuriy - 请参阅:differences between StringBuilder in Java and C#)中的回答。
答案 15 :(得分:2)
我经常使用的另一个集合是用于合并IDictionary方法:
public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> d, TKey key, Func<TValue> valueThunk)
{
TValue v = d.Get(key);
if (v == null)
{
v = valueThunk();
d.Add(key, v);
}
return v;
}
public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> d, TKey key, TValue coalesce)
{
return Get(d, key, () => coalesce);
}
通常用于处理集合:
public static IEnumerable<T> AsCollection<T>(this T item)
{
yield return item;
}
然后是树状结构:
public static LinkedList<T> Up<T>(this T node, Func<T, T> parent)
{
var list = new LinkedList<T>();
node.Up(parent, n => list.AddFirst(n));
return list;
}
因此,我可以轻松地遍历并操作类似以下的类:
class Category
{
public string Name { get; set; }
public Category Parent { get; set; }
}
接下来,为了便于在C#中使用函数组合和更多F#编程方式:
public static Func<T, T> Func<T>(this Func<T, T> f)
{
return f;
}
public static Func<T1, R> Compose<T1, T2, R>(this Func<T1, T2> f, Func<T2, R> g)
{
return x => g(f(x));
}
答案 16 :(得分:2)
允许更多功能性组合码:
public static Func<T, R> TryCoalesce<T, R>(this Func<T, R> f, R coalesce)
{
return x =>
{
try
{
return f(x);
}
catch
{
return coalesce;
}
};
}
public static TResult TryCoalesce<T, TResult>(this Func<T, TResult> f, T p, TResult coalesce)
{
return f.TryCoalesce(coalesce)(p);
}
然后我可以这样写:
public static int ParseInt(this string str, int coalesce)
{
return TryCoalesce(int.Parse, str, coalesce);
}
答案 17 :(得分:1)
这里有几个。
这个将获得一个月的最后一个日期:
<System.Runtime.CompilerServices.Extension()> _
Public Function GetLastMonthDay(ByVal Source As DateTime) As DateTime
Dim CurrentMonth As Integer = Source.Month
Dim MonthCounter As Integer = Source.Month
Dim LastDay As DateTime
Dim DateCounter As DateTime = Source
LastDay = Source
Do While MonthCounter = CurrentMonth
DateCounter = DateCounter.AddDays(1)
MonthCounter = DateCounter.Month
If MonthCounter = CurrentMonth Then
LastDay = DateCounter
End If
Loop
Return LastDay
End Function
这两个使反射更容易:
<System.Runtime.CompilerServices.Extension()> _
Public Function GetPropertyValue(Of ValueType)(ByVal Source As Object, ByVal PropertyName As String) As ValueType
Dim pInfo As System.Reflection.PropertyInfo
pInfo = Source.GetType.GetProperty(PropertyName)
If pInfo Is Nothing Then
Throw New Exception("Property " & PropertyName & " does not exists for object of type " & Source.GetType.Name)
Else
Return pInfo.GetValue(Source, Nothing)
End If
End Function
<System.Runtime.CompilerServices.Extension()> _
Public Function GetPropertyType(ByVal Source As Object, ByVal PropertyName As String) As Type
Dim pInfo As System.Reflection.PropertyInfo
pInfo = Source.GetType.GetProperty(PropertyName)
If pInfo Is Nothing Then
Throw New Exception("Property " & PropertyName & " does not exists for object of type " & Source.GetType.Name)
Else
Return pInfo.PropertyType
End If
End Function
答案 18 :(得分:1)
我讨厌在任何地方都这样做:
DataSet ds = dataLayer.GetSomeData(1, 2, 3);
if(ds != null){
if(ds.Tables.Count > 0){
DataTable dt = ds.Tables[0];
foreach(DataRow dr in dt.Rows){
//Do some processing
}
}
}
相反,我通常使用以下扩展方法:
public static IEnumerable<DataRow> DataRows(this DataSet current){
if(current != null){
if(current.Tables.Count > 0){
DataTable dt = current.Tables[0];
foreach(DataRow dr in dt.Rows){
yield return dr;
}
}
}
}
所以第一个例子就变成了:
foreach(DataRow row in ds.DataRows()){
//Do some processing
}
Yay,扩展方法!
答案 19 :(得分:1)
我个人收集的字符串utils中的我最喜欢的是能够解析任何具有TryParse方法的类型的字符串中的强类型值:
public static class StringUtils
{
/// <summary>
/// This method will parse a value from a string.
/// If the string is null or not the right format to parse a valid value,
/// it will return the default value provided.
/// </summary>
public static T To<t>(this string value, T defaultValue)
where T: struct
{
var type = typeof(T);
if (value != null)
{
var parse = type.GetMethod("TryParse", new Type[] { typeof(string), type.MakeByRefType() });
var parameters = new object[] { value, default(T) };
if((bool)parse.Invoke(null, parameters))
return (T)parameters[1];
}
return defaultValue;
}
/// <summary>
/// This method will parse a value from a string.
/// If the string is null or not the right format to parse a valid value,
/// it will return the default value for the type.
/// </summary>
public static T To<t>(this string value)
where T : struct
{
return value.To<t>(default(T));
}
}
从查询字符串中获取强类型信息非常棒:
var value = Request.QueryString["value"].To<int>();
答案 20 :(得分:1)
int上的扩展方法,用于解码指定日期(在本例中为星期一是星期一)的位掩码到DayOfWeek枚举的枚举:
public static IEnumerable<DayOfWeek> Days(this int dayMask)
{
if ((dayMask & 1) > 0) yield return DayOfWeek.Monday;
if ((dayMask & 2) > 0) yield return DayOfWeek.Tuesday;
if ((dayMask & 4) > 0) yield return DayOfWeek.Wednesday;
if ((dayMask & 8) > 0) yield return DayOfWeek.Thursday;
if ((dayMask & 16) > 0) yield return DayOfWeek.Friday;
if ((dayMask & 32) > 0) yield return DayOfWeek.Saturday;
if ((dayMask & 64) > 0) yield return DayOfWeek.Sunday;
}
答案 21 :(得分:1)
这个创建了一开始就添加了单个元素的数组:
public static T[] Prepend<T>(this T[] array, T item)
{
T[] result = new T[array.Length + 1];
result[0] = item;
Array.Copy(array, 0, result, 1, array.Length);
return result;
}
string[] some = new string[] { "foo", "bar" };
...
some = some.Prepend("baz");
当我需要将某个表达式转换为正方形时,这个可以帮助我:
public static double Sq(this double arg)
{
return arg * arg;
}
(x - x0).Sq() + (y - y0).Sq() + (z - z0).Sq()
答案 22 :(得分:1)
经常使用StringBuilder,您可能会发现需要组合AppendFormat()和AppendLine()。
public static void AppendFormatLine(this StringBuilder sb, string format, params object[] args)
{
sb.AppendFormat(format, args);
sb.AppendLine();
}
另外,由于我将应用程序从VB6转换为C#,以下内容对我非常有用:
public static string Left(this string s, int length)
{
if (s.Length >= length)
return s.Substring(0, length);
throw new ArgumentException("Length must be less than the length of the string.");
}
public static string Right(this string s, int length)
{
if (s.Length >= length)
return s.Substring(s.Length - length, length);
throw new ArgumentException("Length must be less than the length of the string.");
}
答案 23 :(得分:1)
public static class ObjectExtension
{
public static T As<T>(this object value)
{
return (value != null && value is T) ? (T)value : default(T);
}
public static int AsInt(this string value)
{
if (value.HasValue())
{
int result;
var success = int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out result);
if (success)
{
return result;
}
}
return 0;
}
public static Guid AsGuid(this string value)
{
return value.HasValue() ? new Guid(value) : Guid.Empty;
}
}
字符串扩展
public static class StringExtension
{
public static bool HasValue(this string value)
{
return string.IsNullOrEmpty(value) == false;
}
public static string Slug(this string value)
{
if (value.HasValue())
{
var builder = new StringBuilder();
var slug = value.Trim().ToLower();
foreach (var c in slug)
{
switch (c)
{
case ' ':
builder.Append("-");
break;
case '&':
builder.Append("and");
break;
default:
if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') && c != '-')
{
builder.Append(c);
}
break;
}
}
return builder.ToString();
}
return string.Empty;
}
public static string Truncate(this string value, int limit)
{
return (value.Length > limit) ? string.Concat(value.Substring(0, Math.Min(value.Length, limit)), "...") : value;
}
}
最后是一些枚举扩展
public static class EnumExtensions
{
public static bool Has<T>(this Enum source, params T[] values)
{
var value = Convert.ToInt32(source, CultureInfo.InvariantCulture);
foreach (var i in values)
{
var mask = Convert.ToInt32(i, CultureInfo.InvariantCulture);
if ((value & mask) == 0)
{
return false;
}
}
return true;
}
public static bool Has<T>(this Enum source, T values)
{
var value = Convert.ToInt32(source, CultureInfo.InvariantCulture);
var mask = Convert.ToInt32(values, CultureInfo.InvariantCulture);
return (value & mask) != 0;
}
public static T Add<T>(this Enum source, T v)
{
var value = Convert.ToInt32(source, CultureInfo.InvariantCulture);
var mask = Convert.ToInt32(v, CultureInfo.InvariantCulture);
return Enum.ToObject(typeof(T), value | mask).As<T>();
}
public static T Remove<T>(this Enum source, T v)
{
var value = Convert.ToInt32(source, CultureInfo.InvariantCulture);
var mask = Convert.ToInt32(v, CultureInfo.InvariantCulture);
return Enum.ToObject(typeof(T), value & ~mask).As<T>();
}
public static T AsEnum<T>(this string value)
{
try
{
return Enum.Parse(typeof(T), value, true).As<T>();
}
catch
{
return default(T);
}
}
}
答案 24 :(得分:1)
我喜欢this one。它是String.Split方法的一种变体,它允许使用转义字符来抑制当拆分字符位于实际字符串中时的拆分。
答案 25 :(得分:1)
我在这里提到了一些我使用的:
Easier checking on flags enums
if( enumVar.IsSet( MyEnum.PossibleFlag ) ) //..then
myObject.IfNotNull( x => x.Property );
答案 26 :(得分:1)
这是我写的另一篇:
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 < 0) throw new ArgumentOutOfRangeException("startIndex", "Must be positive.");
if (endIndex < 0) throw new ArgumentOutOfRangeException("endIndex", "Must be positive.");
if (startIndex > endIndex) throw new ArgumentOutOfRangeException("endIndex", "Must be >= startIndex.");
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)) throw new ArgumentNullException("startText", "Must be filled.");
if (string.IsNullOrEmpty(endText)) throw new ArgumentNullException("endText", "Must be filled.");
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);
}
}
这个背后的动机很简单。它始终告诉我内置的Substring方法如何将startindex和length作为参数。使用startindex和endindex总是更有帮助。所以,我自己动手:
用法:
string s = "This is a tester for my cool extension method!!";
s = s.Subsetstring("tester", "cool",true);
我必须使用Subsetstring的原因是因为Substring的重载已经需要两个整数。如果有人有更好的名字,请告诉我!!
答案 27 :(得分:1)
我最常用的扩展方法必须是System.Linq.Enumerable
类中的扩展方法。
您可以在MoreLinq找到该列表的有用且有用的扩展。
答案 28 :(得分:0)
在多线程WPF应用程序中(例如,当您使用套接字或定时器时)我经常需要调用GUI线程来更改WPF元素属性。这是丑陋的代码,特别是因为您需要为每个方法执行此操作。这就是我制作这种扩展方法的原因:
/// <summary>
/// Invoke the element's thread using a dispatcher. This is needed for changing WPF element attributes.
/// </summary>
/// <param name="dispatcherObject">The element of which to use the thread.</param>
/// <param name="action">The action to do with the invoked thread.</param>
/// <param name="dispatcherPriority">The priority of this action.</param>
public static void DoInvoked(this System.Windows.Threading.DispatcherObject dispatcherObject, Action action, System.Windows.Threading.DispatcherPriority dispatcherPriority = System.Windows.Threading.DispatcherPriority.Render)
{
if (System.Threading.Thread.CurrentThread == dispatcherObject.Dispatcher.Thread)
{
action();
}
else
{
dispatcherObject.Dispatcher.BeginInvoke(action, dispatcherPriority, null);
}
}
实现:
public partial class MainWindow : Window
{
... other code ...
void updateTime(object sender, ElapsedEventArgs e)
{
this.DoInvoked(() => textBoxStatus.Text = "Done.");
}
}
答案 29 :(得分:0)
我可能最常使用约束类型。
类似的东西:
public class Gallons
{
private int m_gallons;
public Gallons(int count)
{
if(count < 0)
throw new ArgumentException("Cannot have negative gallons");
m_gallons = count;
}
static public Gallons operator + (Gallons left, Gallons right)
{
return new Gallons(left.m_gallons + right.m_gallons);
}
public override string ToString()
{
return m_gallons.ToString();
}
}
public class Feet
{
private int m_feet;
public Feet(int count)
{
if(count < 0)
throw new ArgumentException("Cannot have negative feet");
m_feet = count;
}
static public Feet operator +(Feet left, Feet right)
{
return new Feet(left.m_feet + right.m_feet);
}
public override string ToString()
{
return m_feet.ToString();
}
}
public static class Conversions
{
static public Feet Feet(this int i)
{
return new Feet(i);
}
static public Gallons Gallons(this int i)
{
return new Gallons(i);
}
}
public class Test
{
static public int Main(string[] args)
{
System.Console.WriteLine(2.Feet() + 3.Feet()); // 5
System.Console.WriteLine(3.Gallons() + 4.Gallons()); // 7
System.Console.WriteLine(2.Feet() + 3.Gallons()); // doesn't compile - can't add feet to gallons!
return 0;
}
}
答案 30 :(得分:0)
其中一些已经发布,但我只是想说我已经看过很多这些主题并且投票永远不会与有用的实际情况相匹配。 IMO,这是真正最有用的扩展方法列表
someCollection.ForEach(i => i.DoSomething());
这非常有用,因为它取代了内置的foreach语句,我们都知道它的使用频率。
7.CreateSequence();
这只创建一个从0到6的序列。可以有其他版本,例如指定起点和步骤。这是第二个最有用的函数,因为它取代了for循环。有些人说这复制了Enumerable.Range函数,这是真的,但是我喜欢linq的一个方法是从左到右排序,所以你可以做这样的事情
myCollection.Where(i => i.Something == somethingElse).Count().CreateSequence(). do something else
下一个最有用的是CastTo和As。它们再次复制了内置功能,但它们保留了从左到右的顺序。请注意,CastTo与Cast的不同之处在于CastTo适用于单个对象。
myObject.CastTo<Person>().DoSomething()
myObject.As<Person>()
然后是SplitAsEnumerable。这与split相同,但不会立即将所有内容加载到内存中。这非常适合解析大文件。它适用于字符串或流。
myFileStream.SplitAsEnumerable("\r\n").Select(line => line.SplitAsEnumerable(","))
最后一种是将集合转换为字符串的方法。这非常适合在屏幕上显示内容或写入文件。例如:
myTextBox.Text = "Top 3 scorers are " + myCollection.OrderBy(i => i.Score).Take(3).FlattenToString(i => i.Score.ToString(), ", ");
答案 31 :(得分:0)
这是我经常用来从流复制到另一个流中的东西,特别是用于将东西复制到MemoryStream中。
public static void CopyStream(this Stream destination, Stream source)
{
if (source.CanSeek)
{
source.Position = 0;
}
int Length = 64000;
Byte[] buffer = new Byte[Length];
int bytesRead = source.Read(buffer, 0, Length);
// write the required bytes
while (bytesRead > 0)
{
destination.Write(buffer, 0, bytesRead);
bytesRead = source.Read(buffer, 0, Length);
}
}
实现:
MemoryStream result = new MemoryStream();
Stream s = new FileStream(tempDocFile, FileMode.Open);
result.CopyStream(s);
s.Close();
答案 32 :(得分:0)
虽然我没有写这两个 - 我希望我有。找到http://lostechies.com/jimmybogard/2009/10/16/more-missing-linq-operators/
<强>追加强>
public static IEnumerable<TSource> Append<TSource>(this IEnumerable<TSource> source, TSource element)
{
using (IEnumerator<TSource> e1 = source.GetEnumerator())
while (e1.MoveNext())
yield return e1.Current;
yield return element;
}
<强>前置强>
public static IEnumerable<TSource> Prepend<TSource>(this IEnumerable<TSource> source, TSource element)
{
yield return element;
using (IEnumerator<TSource> e1 = source.GetEnumerator())
while (e1.MoveNext())
yield return e1.Current;
}
答案 33 :(得分:0)
将给定fileinfo类的任何给定属性与另一个属性进行比较..
public static bool compare(this FileInfo F1,FileInfo F2,string propertyName)
{
try
{
System.Reflection.PropertyInfo p1 = F1.GetType().GetProperty(propertyName);
System.Reflection.PropertyInfo p2 = F2.GetType().GetProperty(propertyName);
if (p1.GetValue(F1, null) == p2.GetValue(F1, null))
{
return true;
}
}
catch (Exception ex)
{
return false;
}
return false;
}
答案 34 :(得分:0)
这是我最近在工作中写的一篇博文:
http://crazorsharp.blogspot.com/2009/03/cool-ienumberable-extension-method_25.html
它基本上是IEnumerable.ToHtmlTable();
答案 35 :(得分:0)
曾与 实体框架 &amp;我一遍又一遍地使用了一行代码?
_context.EmployeeSet.Include("Department")
.Include("Manager").Include( ... ).Select();
这样做不容易:
_context.EmployeeSet.IncludeCommonReferenceses().Select();
`
internal static class ObjectContextExtensions
{
internal static ObjectQuery<Employee> IncludeCommonReferenceses(this ObjectQuery<Employee> employeeSet)
{
return employeeSet.Include(GetPropertyName<Employee>(e => e.Department))
.Include(GetPropertyName<Employee>(e => e.Manager)).Include( ... );
}
private static string GetPropertyName<T>(Expression<Func<T, object>> subSelector)
{
return ((MemberExpression)subSelector.Body).Member.Name;
}
}
我建议你在consts中保存属性名称以避免使用反射和&amp;超过agasin。
答案 36 :(得分:0)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string guid1 = "936DA01F-9ABD-4d9d-80C7-02AF85C822A8";
string guid2 = "936DA01F-9ABD-4d9d-80C7-02AF85C822A";
Console.WriteLine("guid1: {0}", guid1.IsGuid());
Console.WriteLine("guid2: {0}", guid2.IsGuid());
Console.ReadLine();
}
}
public static class GuidUtility
{
/// <summary>
/// Determines if string is legitimate GUID
/// </summary>
public static Boolean IsGuid(this String s)
{
string pattern = @"^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$";
Regex regex = new Regex(pattern);
return regex.IsMatch(s);
}
}
}
答案 37 :(得分:0)
我自动导航以下内容来解决MVC项目中的class-name-upper-case-url问题:
public static class RouteCollectionExt
{
public static Route MapRouteLowercase(this RouteCollection routes, string name, string url, object defaults)
{
var route = new LowercaseRoute(url, new RouteValueDictionary(defaults), new MvcRouteHandler());
routes.Add(name, route);
return route;
}
private class LowercaseRoute : Route
{
public LowercaseRoute(string url, IRouteHandler routeHandler)
: base(url, routeHandler) { }
public LowercaseRoute(string url, RouteValueDictionary defaults, IRouteHandler routeHandler)
: base(url, defaults, routeHandler) { }
public LowercaseRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler)
: base(url, defaults, constraints, routeHandler) { }
public LowercaseRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler)
: base(url, defaults, constraints, dataTokens, routeHandler) { }
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
var path = base.GetVirtualPath(requestContext, values);
if (path != null)
{
path.VirtualPath = path.VirtualPath.ToLowerInvariant();
}
return path;
}
}
}
用法:
routes.MapRouteLowercase(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
答案 38 :(得分:0)
String.format不应该是静态的。所以我使用了一个名为frmt的扩展方法:
<Extension()> Public Function frmt(ByVal format As String,
ByVal ParamArray args() As Object) As String
If format Is Nothing Then Throw New ArgumentNullException("format")
Return String.Format(format, args)
End Function
当我想在不构造二进制编写器的情况下读取或写入字节流的数字时(从技术上讲,在用编写器包装后不应修改原始流):
<Extension()> Public Function Bytes(ByVal n As ULong,
ByVal byteOrder As ByteOrder,
Optional ByVal size As Integer = 8) As Byte()
Dim data As New List(Of Byte)
Do Until data.Count >= size
data.Add(CByte(n And CULng(&HFF)))
n >>= 8
Loop
Select Case byteOrder
Case ByteOrder.BigEndian
Return data.ToArray.reversed
Case ByteOrder.LittleEndian
Return data.ToArray
Case Else
Throw New ArgumentException("Unrecognized byte order.")
End Select
End Function
<Extension()> Public Function ToULong(ByVal data As IEnumerable(Of Byte),
ByVal byteOrder As ByteOrder) As ULong
If data Is Nothing Then Throw New ArgumentNullException("data")
Dim val As ULong
Select Case byteOrder
Case ByteOrder.LittleEndian
data = data.Reverse
Case ByteOrder.BigEndian
'no change required
Case Else
Throw New ArgumentException("Unrecognized byte order.")
End Select
For Each b In data
val <<= 8
val = val Or b
Next b
Return val
End Function
答案 39 :(得分:0)
这一个移动一个序列,以便您首先获得给定的项目。例如,我用它来取几周的时间并将其移动,以便序列中的第一天是当前文化的一周的第一天。
/// <summary>
/// Shifts a sequence so that the given <paramref name="item"/> becomes the first.
/// Uses the specified equality <paramref name="comparer"/> to find the item.
/// </summary>
/// <typeparam name="TSource">Type of elements in <paramref name="source"/>.</typeparam>
/// <param name="source">Sequence of elements.</param>
/// <param name="item">Item which will become the first.</param>
/// <param name="comparer">Used to find the first item.</param>
/// <returns>A shifted sequence. For example Shift({1,2,3,4,5,6}, 3) would become {3,4,5,6,1,2}. </returns>
public static IEnumerable<TSource> Shift<TSource>(this IEnumerable<TSource> source, TSource item, IEqualityComparer<TSource> comparer)
{
var queue = new Queue<TSource>();
bool found = false;
foreach (TSource e in source)
{
if (!found && comparer.Equals(item, e))
found = true;
if (found)
yield return e;
else
queue.Enqueue(e);
}
while (queue.Count > 0)
yield return queue.Dequeue();
}
/// <summary>
/// Shifts a sequence so that the given item becomes the first.
/// Uses the default equality comparer to find the item.
/// </summary>
/// <typeparam name="TSource">Type of elements in <paramref name="source"/>.</typeparam>
/// <param name="source">Sequence of elements.</param>
/// <param name="element">Element which will become the first.</param>
/// <returns>A shifted sequence. For example Shift({1,2,3,4,5,6}, 3) would become {3,4,5,6,1,2}. </returns>
public static IEnumerable<TSource> Shift<TSource>(this IEnumerable<TSource> source, TSource element)
{
return Shift(source, element, EqualityComparer<TSource>.Default);
}