una rural método metodos metodo genérica extensión extension estática definirse definicion debe conjuntos clase c# .net extension-methods syntactic-sugar

c# - método - metodos de extension rural



¿Cuál es el mejor o más interesante uso de los Métodos de extensión que ha visto? (30)

Aquí hay uno que corté juntos, así que siéntete libre de hacer agujeros en él. Toma una lista (ordenada) de enteros y devuelve una lista de cadenas de rangos contiguos. p.ej:

1,2,3,7,10,11,12 --> "1-3","7","10-12"

La función (dentro de una clase estática):

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

Ejemplo de uso:

this.WeekDescription = string.Join(",", from.WeekPattern.WeekPatternToInts().IntRanges().ToArray());

Este código se usa para convertir datos de una aplicación digna de horario digna de DailyWTF. WeekPattern es una máscara de bits almacenada en una cadena "0011011100 ...". WeekPatternToInts () lo convierte en un IEnumerable <int>, en este caso [3,4,6,7,8], que se convierte en "3-4,6-8". Proporciona al usuario una descripción compacta de los rangos académicos semanales en los que se desarrolla una conferencia.

Estoy empezando a amar de verdad los métodos de extensión ... Me preguntaba si alguien se topa con uno que realmente le voló la cabeza, o simplemente lo encontró listo.

Un ejemplo que escribí hoy:

Editado debido a los comentarios de otros usuarios:

public static IEnumerable<int> To(this int fromNumber, int toNumber) { while (fromNumber < toNumber) { yield return fromNumber; fromNumber++; } }

Esto permite que un bucle for se escriba como un bucle foreach:

foreach (int x in 0.To(16)) { Console.WriteLine(Math.Pow(2, x).ToString()); }

¡No puedo esperar para ver otros ejemplos! ¡Disfrutar!


Aunque es muy simple, creo que este es particularmente útil ya que obtengo una página de un conjunto de resultados completo diez mil millones de veces por proyecto:

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


Bueno, esto no es exactamente inteligente, pero modifiqué los métodos de --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

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

Es increíble simple pero realmente ayuda a limpiar esos controles nulos. Se usa mejor cuando su UI está esperando una lista de elementos X, como un sistema de torneo o máquinas tragamonedas de jugador del juego y desea mostrar "asientos vacíos".

Uso:

return jediList.SingleOrDefault( j => j.LightsaberColor == "Orange", new Jedi() { LightsaberColor = "Orange", Name = "DarthNobody");


Dos de los que me gustaría usar son los métodos de extensión InsertWhere <T > y RemoveWhere <T > que he escrito. Trabajando con ObservableCollections en WPF y Silverlight a menudo necesito modificar listas ordenadas sin volver a crearlas. Estos métodos me permiten insertar y eliminar de acuerdo con un Func suministrado, por lo que no es necesario volver a llamar a .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); }

Editar:
Talljoe hizo algunas mejoras significativas en RemoveWhere / RemoveAll, que construí apresuradamente. Con ~ 3mill items eliminando cada tercio, la nueva versión toma solo ~ 50 milisegundos (menos de 10 si puede llamar a List.RemoveAll!) En lugar de los múltiples segundos de RemoveWhere (me cansé de esperar).

Aquí está su versión mejorada, ¡gracias de nuevo!

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


Escribí una serie de métodos de extensión para facilitar la manipulación de objetos y métodos de ADO.NET:

Crea un DbCommand desde un DbConnection en una instrucción:

public static DbCommand CreateCommand(this DbConnection connection, string commandText) { DbCommand command = connection.CreateCommand(); command.CommandText = commandText; return command; }

Agregue un parámetro a un 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; }

Acceda a los campos de DbDataReader por nombre en lugar de índice:

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

Otro método de extensión (no relacionado) me permite realizar la operación DragMove (como en WPF) en formularios y controles de WinForms, consulte aquí .


Esta es una de las que últimamente ha estado recibiendo algo de mi juego:

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

Usado como:

using (Html.Tag("ul")) { this.Model.ForEach(item => using(Html.Tag("li")) Html.Write(item)); using(Html.Tag("li")) Html.Write("new"); }

Memento es una clase útil:

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

Y para completar las dependencias:

public static void Write(this HtmlHelper html, string content) { if (html == null) throw new ArgumentNullException("html"); html.ViewContext.HttpContext.Response.Write(content); }


Este es increíblemente simple, pero es un cheque que hago mucho, así que terminé haciendo un método de extensión para él. Mis métodos de extensión favoritos tienden a ser los más sencillos y sencillos como este, o como el método de extensión de Taylor L''para generar eventos.

public static bool IsNullOrEmpty(this ICollection e) { return e == null || e.Count == 0; }


Este es un método de extensión para centralizar las comprobaciones nulas antes de generar eventos.

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


Estoy convirtiendo una gran cantidad de Java en C #. Muchos de los métodos varían solo en mayúsculas u otras pequeñas diferencias de sintaxis. Así que el código de Java como

myString.toLowerCase();

no se compilará sino agregando un método de extensión

public static void toLowerCase(this string s) { s.ToLower(); }

Puedo capturar todos los métodos (¿y supongo que un buen compilador lo hará de todos modos?).

Sin duda, hizo el trabajo mucho más fácil y más confiable. (Agradezco a @Yuriy - vea la respuesta en: diferencias entre StringBuilder en Java y C # ) para la sugerencia.


La mayoría de los ejemplos de métodos de extensión que veo aquí van en contra de las mejores prácticas. Los métodos de extensión son potentes, pero deben usarse con moderación. En mi experiencia, una clase de ayuda / utilidad estática con sintaxis de la vieja escuela generalmente sería preferible para la mayoría de estos.

Hay algo que decir para los métodos de extensión para los Enums, ya que no es posible que tengan métodos. Si los define en el mismo espacio de nombres que su Enum y en el mismo conjunto, funcionan de forma transparente.


La solución completa es demasiado grande para ponerla aquí, pero escribí una serie de métodos de extensión que le permitirían convertir fácilmente una DataTable en un 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; }

Al final del día, podrías llamarlo así:

someDataTable.ToCSV(); //Plain old CSV someDataTable.ToCSV("/""); //Double quote qualifier someDataTable.ToCSV("/"", "/t"); //Tab delimited


Método de extensión en int para decodificar una máscara de bits que especifica días (en este caso, el primer día de la semana es lunes) a una enumeración de las enumeraciones de 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; }


Me gusta este . Es una variación del método String.Split que permite el uso de un carácter de escape para suprimir la división cuando se pretende que el carácter dividido esté en la cadena real.


Muchas veces, he necesitado mostrar un valor fácil de usar basado en un valor de Enum, pero no quería ir a la ruta de atributo personalizada, ya que no parecía demasiado elegante.

Con este práctico método de extensión:

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

Puedo hacer esto:

Console.WriteLine(MyEnum.First.EnumValue());

¡Hurra!


No soy INotifyPropertyChanged interfaz INotifyPropertyChanged que requiere que los nombres de las propiedades pasen como cadenas. Quiero una forma fuertemente tipada para comprobar en tiempo de compilación que solo estoy elevando y manejando los cambios de propiedad de las propiedades que existen. Yo uso este código para hacer eso:

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

En las clases que implementan INotifyPropertyChanged , INotifyPropertyChanged este método de ayuda:

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

Para que finalmente pueda hacer este tipo de cosas:

private string _name; public string Name { get { return _name; } set { this.NotifySetProperty(ref _name, value, () => this.Name); } }

Está fuertemente tipado y solo planteo eventos para propiedades que realmente cambian su valor.


Otro conjunto que utilizo con bastante frecuencia es para combinar los métodos 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); }

Y para trabajar con colecciones en general:

public static IEnumerable<T> AsCollection<T>(this T item) { yield return item; }

Luego, para estructuras arbóreas:

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

Entonces puedo atravesar y operar fácilmente en una clase como esta:

class Category { public string Name { get; set; } public Category Parent { get; set; } }

A continuación, para facilitar la composición de funciones y una forma más F # de programación en C #:

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


Para permitir un código combinador más funcional:

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

Entonces podría escribir algo como esto:

public static int ParseInt(this string str, int coalesce) { return TryCoalesce(int.Parse, str, coalesce); }


Tengo varios métodos de extensión .Debugify que son útiles para arrojar objetos a un archivo de registro. Por ejemplo, aquí está mi Diccionario debugify (tengo estos para List, Datatable, param array, etc.):

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

Y aquí hay uno para DbParameterCollection (útil para volcar las llamadas a la base de datos al archivo de registro):

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

Ejemplo de resultado:

Log.DebugFormat("EXEC {0} {1}", procName, params.Debugify); // EXEC spProcedure @intID=5, @nvName=''Michael Haren'', @intRefID=11 OUTPUT

Tenga en cuenta que si llama a esto después de las llamadas a su base de datos, también obtendrá los parámetros de salida completados. Llamo esto a una línea que incluye el nombre de SP para poder copiar / pegar la llamada en SSMS para la depuración.

Estos hacen que mis archivos de registro sean bonitos y fáciles de generar sin interrumpir mi código.


Un par de métodos de extensión para convertir cadenas de base 36 (!) En enteros:

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

(Algunos genios decidieron que la mejor manera de almacenar números en la base de datos era codificarlos en cadenas. Los decimales ocupan demasiado espacio. El maleficio es mejor, pero no usa los caracteres GZ. ¡Así que obviamente extiendes la base 16 a la base 36! )


Here''s another one I wrote:

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

The motivation behind this one was simple. It always bugged me how the built in Substring method took startindex and length as it''s parameters. It''s ALWAYS much more helpful to do startindex and endindex. So, I rolled my own:

Uso:

string s = "This is a tester for my cool extension method!!"; s = s.Subsetstring("tester", "cool",true);

The reason I had to use Subsetstring was because Substring''s overload already takes two ints. If anyone has a better name, please, let me know!!


I hate having to do this everywhere:

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

Instead I usually use the following Extension Method:

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

So the first example then becomes:

foreach(DataRow row in ds.DataRows()){ //Do some processing }

Yay, Extension Methods!


My favourite from my own personal collection of string utils is one that will parse a strongly typed value from a string for any type that has a TryParse method:

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

It''s great for getting strongly typed information from query strings:

var value = Request.QueryString["value"].To<int>();


String.format should not have been static. So I use an extension method called 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

When I want to read or write a number to a byte stream without constructing a binary writer (technically you aren''t supposed to modify the raw stream after you''ve wrapped it with a writer):

<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


The extension methods I use the most would have to be the ones in the System.Linq.Enumerable class.

And a good and useful extension to that list you can find in MoreLinq .



This one creates array with single element added at the very beginning:

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

And this one helps me when I need to convert some expression to it''s square:

public static double Sq(this double arg) { return arg * arg; } (x - x0).Sq() + (y - y0).Sq() + (z - z0).Sq()


With regular use of StringBuilder, you may see the need to combine AppendFormat() and AppendLine().

public static void AppendFormatLine(this StringBuilder sb, string format, params object[] args) { sb.AppendFormat(format, args); sb.AppendLine(); }

Also, since I''m converting an application from VB6 to C#, the following are very useful to me:

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


cool, also loving Extensions!

here''s a few.

This one will get the last Date of a Month:

<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

these two make reflection a bit easier:

<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


few extensions I use mostly. first set is object extensions, really only for converting.

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

string extensions

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

and last is some enum extensions

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


Éste cambia una secuencia para que puedas obtener el elemento dado primero. Lo usé, por ejemplo, para tomar el día de semanas y cambiarlo para que el primer día de la secuencia sea el primer día de la semana para la cultura actual.

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