На данный момент это все еще не поддерживается из коробки компилятором Roslyn ...
До сих пор свойства расширения не рассматривались как достаточно ценные для включения в предыдущие версии стандарта C #. C # 7 и C # 8.0 считают это чемпионом предложения, но оно еще не было выпущено, прежде всего потому, что, даже если уже есть реализация, они хотят сделать это с самого начала.
Но это будет ...
В рабочем списке C # 7 есть элемент расширения, поэтому он может быть поддержан в ближайшем будущем. Текущий статус свойства extension можно найти на Github под соответствующим элементом .
Тем не менее, есть еще более многообещающая тема, которая заключается в том, чтобы «расширить все», уделяя особое внимание свойствам, статическим классам или даже полям.
Кроме того, вы можете использовать обходной путь
Как указано в этой статье , вы можете использовать TypeDescriptorвозможность прикрепить атрибут к экземпляру объекта во время выполнения. Однако он не использует синтаксис стандартных свойств.
Это немного отличается от простого синтаксического сахара, добавляющего возможность определять расширенное свойство, например,
string Data(this MyClass instance)в качестве псевдонима для метода расширения, так
string GetData(this MyClass instance)как оно хранит данные в классе.
Я надеюсь, что C # 7 обеспечит полнофункциональное расширение всего (свойств и полей), однако на данный момент только время покажет.
И не стесняйтесь вносить свой вклад, поскольку программное обеспечение завтрашнего дня придет от сообщества.
Обновление: август 2016
Как команда dotnet опубликовала, что нового в C # 7.0 и из комментария Мадса Торгенсена :
Свойства расширения: у нас был (блестящий!) Стажер, который реализовывал их летом в качестве эксперимента, вместе с другими видами членов расширения. Мы по-прежнему заинтересованы в этом, но это большое изменение, и мы должны быть уверены, что оно того стоит.
Кажется, что свойства расширения и другие члены все еще являются хорошими кандидатами для включения в будущий выпуск Roslyn, но, возможно, не 7.0.
Обновление: май 2017
Члены расширения были закрыты как дубликат вопроса расширения, который тоже закрыт. Основное обсуждение было на самом деле о расширяемости типов в широком смысле. Эта функция теперь отслеживается здесь как предложение и удалена из этапа 7.0 .
Обновление: август 2017 г. - C # 8.0 предлагаемая функция
Хотя это все еще остается только предложенной функцией, теперь у нас есть более четкое представление о том, каким будет ее синтаксис. Имейте в виду, что это будет новый синтаксис и для методов расширения:
public interface IEmployee
{
public decimal Salary { get; set; }
}
public class Employee
{
public decimal Salary { get; set; }
}
public extension MyPersonExtension extends Person : IEmployee
{
private static readonly ConditionalWeakTable<Person, Employee> _employees =
new ConditionalWeakTable<Person, Employee>();
public decimal Salary
{
get
{
// `this` is the instance of Person
return _employees.GetOrCreate(this).Salary;
}
set
{
Employee employee = null;
if (!_employees.TryGetValue(this, out employee)
{
employee = _employees.GetOrCreate(this);
}
employee.Salary = value;
}
}
}
IEmployee person = new Person();
var salary = person.Salary;
Подобно частичным классам, но скомпилирован как отдельный класс / тип в другой сборке. Обратите внимание, что вы также сможете добавлять статические члены и операторы таким образом. Как упоминалось в подкасте Mads Torgensen , расширение не будет иметь никакого состояния (поэтому оно не может добавлять частные элементы экземпляра в класс), что означает, что вы не сможете добавить частные данные экземпляра, связанные с экземпляром . Причина, по которой это вызвано, заключается в том, что это подразумевает управление внутренними словарями, и это может быть сложно (управление памятью и т. Д.). Для этого вы все еще можете использовать метод TypeDescriptor/ ConditionalWeakTable, описанный ранее, и с расширением свойства скрывает его под хорошим свойством.
Синтаксис все еще может быть изменен, поскольку подразумевает эту проблему . Например, extendsможет быть заменено тем, forчто некоторые могут чувствовать себя более естественно и менее связаны с Java.
Обновление декабря 2018 года - роли, расширения и статические члены интерфейса
Расширение все не дошло до C # 8.0, из-за некоторых недостатков, объясненных как конец этого билета GitHub . Итак, было проведено исследование для улучшения дизайна. Здесь Мадс Торгенсен объясняет, что такое роли и расширения и чем они отличаются:
Роли позволяют реализовывать интерфейсы для определенных значений данного типа. Расширения позволяют реализовывать интерфейсы для всех значений данного типа в пределах определенной области кода.
Это можно увидеть при разделении предыдущего предложения в двух случаях использования. Новый синтаксис для расширения будет выглядеть так:
public extension ULongEnumerable of ulong
{
public IEnumerator<byte> GetEnumerator()
{
for (int i = sizeof(ulong); i > 0; i--)
{
yield return unchecked((byte)(this >> (i-1)*8));
}
}
}
тогда вы сможете сделать это:
foreach (byte b in 0x_3A_9E_F1_C5_DA_F7_30_16ul)
{
WriteLine($"{e.Current:X}");
}
И для статического интерфейса :
public interface IMonoid<T> where T : IMonoid<T>
{
static T operator +(T t1, T t2);
static T Zero { get; }
}
Добавить свойство расширения на intи лечить , intкак IMonoid<int>:
public extension IntMonoid of int : IMonoid<int>
{
public static int Zero => 0;
}