Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Один из вариантов – создать для объекта read only интерфейс, из которого исключить все методы, изменяющие объект.
interface IReadOnlyVector
{
// readonly methods and properties
}
interface IVector : IReadOnlyVector
{
// any methods and properties
}
class ReadOnlyVector : IVector, IReadOnlyVector
{
private readonly IVector vector;
public ReadOnlyVector(IVector vector)
{
this.vector = vector;
}
}
class Vector : IVector, IReadOnlyVector
{
public IReadOnlyVector AsReadOnly()
{
return new ReadOnlyVector(this);
}
}
class ReadOnlyVector : IReadOnlyVectorЭто ровно то же самое, что и у меня. Только у меня в ReadOnly сохраняется ссылка на сами данные класса (T[]), а не на сам класс. И вместо моего свойства Reader у Вас AsReadOnly().
И ещё у Вас Vector наследует от IReadOnlyVector, что заставит Вас реализовывать этот интерфейс дважды.
И повторюсь, не всё является обычными коллекциями.
ReadOnlyVector у Вас является оболочкой над Vector, но методы-то в нём Вам всё равно реализовывать. Это и есть то дублирование, которого у меня как раз-таки и нет.
Кстати говоря, я в статье постоянно упоминал про производительность, а Ваш wrapper — это мягко говоря, не очень эффективное решение.
Почему?
Но они не настолько снижают производительность...
Я предлагаю избавиться от дублирования кода реализации
и добавляет сложности в поддерживание кода, т.к. нужно синхронно вносить изменения во все реализации
В данном случае, дублирования нет.
var v = new Vector<int>(5);
v[0] = 0;
Console.WriteLine(v.Reader[0]);
можно запихать его в Vector.
Если вызывать свойство Reader каждый раз при любой операции получится то же, что и у Вас. А при передаче VectorConst в другой метод, Reader или оператор преобразования вызовется только один раз. Получается, что, как ни крути, это выгоднее «Адаптера».
Если свойство Reader настолько уж раздражает, можно запихать его в Vector. пометив как private, и перенаправлять к нему реализацию IVectorConst (или Вашего IReadOnlyVector). И даже это всё равно будет лучше «Адаптера», т.к. вызовы будут происходить не через интерфейс и останется разделение ответственности.
struct Vector<T> : IVector<T>, IVectorConst<T>
{
...
public T this[int nIndex]
{
get { return _reader[nIndex]; }
set { _vector[nIndex] = value; }
}
...
}
struct Vector<T> : IVector<T>
{
...
public T this[int nIndex]
{
get { return _reader[nIndex]; }
set { _vector[nIndex] = value; }
}
...
}
И могу с увереностью сказать, что вы реализовали Декоратор
ваша read-only версия читает данные быстрее, т.к. нет дополнительного вызова, в то время как моя full версия читает быстрее по тем же причинам.
Декоратор служит для динамического подключения поведения, у меня ничего динамического тут нет.
Кстати, там для получения reader'а вообще можно поставить __inline.
Необязательно. Вы декорировали ваш читающий класс методами записи.
MethodImplOptions.AggressiveInlining, если хотите дать совет JIT.
string[] str = new string[1] { "a" }; object[] o = str;Type t = o.GetType(); переменная t будет показывать String[].никакие методы не должны менять содержимое
Я правильно понимаю, что это остается исключительно на контроле разработчика?
const DateTime x = new DateTime(2013, 10, 29); я не могу — компилятор не знает о неизменяемости DateTime, не может её вывести самостоятельно, и я не могу ему помочь. C# не идеален, и это нужно понимать.
Как жить без const?