あなたがあなたの優秀で好きなものを投稿した答えのリストを作りましょう 拡張メソッド 。
必要条件は、完全なコードを掲示しなければならず、それを使用する方法の例と説明が必要であるということです。
このトピックへの高い関心に基づいて、私は Codeplex でextensionoverflowというオープンソースプロジェクトを立ち上げました。
Codeplexプロジェクトにコードを入れることを承認して回答をマークしてください。
リンクではなく完全なソースコードを投稿してください。
Codeplex News:
24.08.2010 Codeplexページはここにあります: http://extensionoverflow.codeplex.com/
11.11.2008XmlSerialize/XmlDeserializeが 実装済み および 単体テスト済み になりました。
11.11.2008まだ多くの開発者がいる余地があります。 ;-)今すぐ参加しよう!
11.11.2008 3人目の貢献者が参加しました ExtensionOverflow 、ようこそ BKristensen
11.11.2008FormatWithは、 実装済み および 単体テスト になりました。
09.11.2008 2人目の貢献者が参加しました ExtensionOverflow 。 chakrit へようこそ。
09.11.2008もっと開発者が必要です。 ;-)
09.11.2008ThrowIfArgumentIsNullが現在 実装済み および 単体テスト がCodeplexにあります。
私はこれを使っています常に:
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, ", ");
そしてもう一つ:
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()が完全にそしてあなたの唯一の他のオプションであるのではるかに有用です):
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
任意の文字列を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();
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());
}
の 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()拡張メソッドのインデックス述語のオーバーロードも追加しました。もっと楽しくするために、追加の「else」述語を含むフレーバーを追加します。
便利な文字列ヘルパー
使用法:
文字列の末尾や先頭にある不要なスペースは嫌いです。文字列はnull
の値をとることがあるので、注意が必要ですので、これを使用します。
public bool IsGroup { get { return !this.GroupName.IsNullOrTrimEmpty(); } }
これは私が新しいために使用する別の拡張方法です 検証フレームワーク 私は試しています。その中の正規表現拡張はきれいでなければ面倒な正規表現を見ることができます:
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ステートメントと名前付きグループを処理するための追加コードを追加するよりも、これらの方が簡単だと思うので、多くの正規表現を実行するのが好きです。
リストを扱うためのいくつかの拡張:
/// <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をリストのように機能させるために、1つ以上のソースからの項目を含む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プロジェクトに入れることができます。
ASP.NET HTML Encode - 短くて甘い
public static string ToHtmlEncodedString(this string s)
{
if (String.IsNullOrEmpty(s))
return s;
return HttpUtility.HtmlEncode(s);
}
インライン変換:この小さなパターンが好きです。 Boolean、Double、およびDateTimeに対して完成しました。 C#isおよびas演算子に従うように設計されています。
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);
{
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();
}
指定したインデックスにある文字列の一部を上書きします。
私はいくつかの入力値が固定幅、固定位置文字列であることを期待するシステムで作業しなければなりません。
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");
ASP.NETでは、FindControlを使用してキャストし、値がnullかどうかを参照する前にチェックする必要があります。そのため、私はTryParse()メソッドを Control に追加しました。これは、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";
}
この種のコードが嫌いですか?
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!
どこでもお気軽にご利用ください。
私はいつもStringBuilder
name__の新しい行が欲しいフォーマットを使っているので、以下の非常に単純な拡張子は数行のコードを節約します:
public static class Extensions
{
public static void AppendLine(this StringBuilder builder,string format, params object[] args)
{
builder.AppendLine(string.Format(format, args));
}
}
代替手段は、\n
またはEnvironment.NewLineを持つAppendFormat
name__内のStringBuilder
name__です。
一般的な試み:
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プロジェクトに配置してください。
まだ回答がありません。
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(",");
有効であれば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;
}
それが二重化されている場合は申し訳ありませんが、私はそれを見つけることはできません。
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プロジェクトに入れることができます
何度か私は自分がGroovyの "Safe navigation"のようなものを望んでいると思いました。
http://groovy.codehaus.org/Statements から:
複雑なオブジェクトグラフを歩いていて、NullPointerExceptionをスローしたくない場合は、?を使用できます。ではなく演算子。ナビゲーションを実行します。
def foo = null def bar = foo?.something?.myMethod()assert bar == null
それで、あなたはそれのために拡張メソッドを追加することは良い考えだと思いますか?何かのようなもの:
obj.SafelyNavigate(x => x.SomeProperty.MaybeAMethod().AnotherProperty);
たとえそれがまた何らかのトラブルをもたらすことができるとしても、私はそれがいいと思うと思います。
あなたがそれが良い考えだと思うなら:
たぶんそれはただ悪い考えです:D、しかし私はそれが正しく行われれば役に立つことができる何かのように見えます。そのようなものがなく、それが何らかの価値を持っていると思うならば、私はそれに打撃を与えて、後で答えを編集するかもしれません。
特にユーザ入力を扱うときには、空白の正規化はかなり便利です。
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+" ) ;
}
}
リフレクションを使用して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>();
Fiscal Yearsで作業する場合に便利な拡張機能
/// <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);
}
これは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;
}
}
}
ASP.NETの場合は、HttpSessionStateのこれらの拡張機能を使用してセッション内のオブジェクトを読み込みます。それはあなたがきれいな方法でセッションオブジェクトをロードすることを可能にし、それらが存在しない場合それらを作成し初期化するでしょう。私はそのように2つの拡張方法を使用します。
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];
}
}
</code>
シリアル化と設定ではDateTimeとしてlongを使うほうが良いでしょう。
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);
}
そして、これが私が定期的に使っているcontrol-invoke拡張です。
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を可能にします。
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);
}
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)を追加するだけです。
環境間で展開するための展開ツールがあります。ファイルは変更されたものとしてマークされることができるが実際には異なるものではないので、私はこれを思い付きました:
/// <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;
}
我々は今朝それを思い付いたので、これは完全には焼かれていません。 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();
もう1つは、今回はクエリパラメータを扱うときに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;
}
私のブログ統計ページの最近の検索セクションで、私はすべての重複を削除しましたが、ほとんど重複する行を削除する方法が必要でした。私はたくさんの似たような、しかし全く同じではないグーグルの質問を得るだろう。
私は辞書の代わりに匿名型を使用することになりましたが、その匿名型のリストを作成する方法を望みました。それはできませんが、.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;
}
// 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
になります。
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);
上記のコードは、渡されたテキスト/値が見つからない場合は何も選択しません。
// 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 ];
}
}
// 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());
}
ペルシャ語を使用していて、その数値をペルシャ語でユーザーに表示する必要がある場合
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;
}
Dbの処理を少し簡単にするためのDataSet/DataRow拡張機能
DataRowで.Field( "fieldname")を使用するだけで、可能であればキャストします。オプションのデフォルトを含めることもできます。
また、DataSet上の.HasRows()なので、テーブルと行の存在を確認する必要はありません。
例:
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);
}
}
Is Allの文字列をチェックする必要がある場合は、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;
}
どうですか….
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
}
あなたが使っているどんなライセンスの下でも、これを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;
}
}
}
テストテスト
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;
}
}
}
私はすべてのコレクションを拡張するために以下の拡張を使います(たぶん誰かがこれらを役に立つと思う):
/// <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;
}
public static class StringHelper
{
public static String F(this String str, params object[] args)
{
return String.Format(str, args);
}
}
Likeを使う:
"Say {0}".F("Hello");
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
);
}
おそらく私が書いて使った最も有用な拡張方法はここにあります:
http://www.codeproject.com/KB/cs/fun-with-cs-extensions.aspx?msg=2838918#xx2838918xx
Equalsをオーバーライドしたり、IEquatable <>を実装したりせずに、2つのオブジェクトの等価性を比較します。
なぜあなたはこれをしたいのですか? 2つのオブジェクトが等しいかどうかを本当に知りたいのですが、Equals(object)
をオーバーライドするかIEquatable<T>
を実装するのが面倒です。もっと現実的に言えば、あなたがひどく複雑なクラスを持っていて、Equalsを手作業で実装することは、非常に面倒で、間違いが起こりやすく、維持するのが楽しくないでしょう。パフォーマンスをあまり気にしないのであれば、これも役に立ちます。
2つ目の理由で、私は現在IsEqualTo
を使用しています - 他のユーザー定義クラスである型を持つ多くのプロパティを持つクラスがあり、それぞれの型は他のユーザー定義クラスである他のプロパティを無限に持ちます。これらのクラスの多くでたくさんのコレクションを投げると、Equals(object)
を実装することは本当に悪夢になります。
使用法:
if (myTerriblyComplexObject.IsEqualTo(myOtherTerriblyComplexObject))
{
// Do something terribly interesting.
}
平等を決定するために、私は多くの比較をします。私は「正しい」順番で「正しい」ものをやろうとします。比較は、順番に次のとおりです。
Equals(object, object)
メソッドを使用してください。 trueが返された場合は、trueを返します。参照が同じ場合はtrueを返します。 thisObject
がEquals(object)
をオーバーライドする場合もtrueを返します。thisObject
がnullの場合、falseを返します。 nullの場合、それ以上の比較はできません。thisObject
がEquals(object)
をオーバーライドしている場合はfalseを返します。これはEqualsをオーバーライドするので、Equalsがステップ#1で実行され、falseが返されたことを意味する必要があります。誰かがEqualsを上書きしたくない場合は、それを尊重し、Equalsが返すものを返す必要があります。thisObject
がIEquatable<T>
を継承している場合(otherObject
をT
に代入できる)、リフレクションを使用してEquals(T)
メソッドを取得します。そのメソッドを呼び出してその戻り値を返します。IEnumerable
である場合、IsEqualToを使用してアイテムを比較することで、同じアイテムを同じ順序で含むかどうかを返します。thisObject
にはEqualsメソッドがないことがわかったので、異なる型の2つのオブジェクトを実際に評価して真となる方法はありません。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();
}
}
}
おや、どうして!これは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