Чи можете ви додати статичні розширення до класів у C #? Ні, але ви можете це зробити:
public static class Extensions
{
public static T Create<T>(this T @this)
where T : class, new()
{
return Utility<T>.Create();
}
}
public static class Utility<T>
where T : class, new()
{
static Utility()
{
Create = Expression.Lambda<Func<T>>(Expression.New(typeof(T).GetConstructor(Type.EmptyTypes))).Compile();
}
public static Func<T> Create { get; private set; }
}
Ось як це працює. Хоча технічно не можна писати статичні методи розширення, натомість цей код використовує лазівку в методах розширення. Ця лазівка полягає в тому, що ви можете викликати методи розширення на нульових об'єктах, не отримуючи нульового винятку (якщо ви нічого не отримуєте через @this).
Отже, ось як би ви цим скористалися:
var ds1 = (null as DataSet).Create(); // as oppose to DataSet.Create()
// or
DataSet ds2 = null;
ds2 = ds2.Create();
// using some of the techniques above you could have this:
(null as Console).WriteBlueLine(...); // as oppose to Console.WriteBlueLine(...)
Тепер ЧОМУ я вибрав за приклад конструктор за замовчуванням, і чому я просто не повертаю новий T () у перший фрагмент коду, не виконуючи все це сміття Expression? Ну сьогодні ваш щасливий день, тому що ви отримуєте 2fer. Як знає будь-який просунутий розробник .NET, новий T () повільний, оскільки він генерує виклик до System.Activator, який використовує відображення, щоб отримати конструктор за замовчуванням, перш ніж викликати його. Чорт за тобою, Microsoft! Однак мій код безпосередньо викликає конструктор за замовчуванням об'єкта.
Статичне розширення було б краще, ніж це, але відчайдушні часи вимагають відчайдушних заходів.