[C#] Свойства-массивы - как работают?
Таким образом, первый вопрос: как это работает?Правильный ответ:
2) Присваивается непосредственно элемент [i, j].Никаких временных массивов не создается.
Быстро, но очень нелогично. Ведь в методе set явно прописано присваивание именно массивов.Вообще, рекомендую заглянуть с помощью ILDasm.exe в CIL-код который сгенерит компилятор. Узнаешь много нового. Например то, что свойство Points на самом деле реализуется с помощью двух методов:
public int[,] get_Points;
public void set_Points(int[,] value);
Далее, когда ты пишешь (допустим, класс, реализующий свойство — MyClass)
MyClass x = new MyClass;
x.Points[0,0] = 0;
то метод set_Points не вызывается. Вызывается только get_Points который возвращает ССЫЛКУ на массив points. Совершенно эквивалентный код:
MyClass x = new MyClass;
int[,] a = x.Points;
a[0,0] = 0;
Здесь переменная a ссылается на массив в поле points, то есть на тот же самый объект в памяти. Вот и всё. Отсюда со всей очевидностью следует ответ на твой вопрос. Всё более чем логично.
Второй вопрос не совсем понял. Вообще-то индексаторы по другому реализуются. Там нужно использовать слово this:
public int this[int i, int j] {
set {
if (i > j) {
points[i, j] = value;
}
}
}
Тогда можно будет обращаться к твоему классу так:
MyClass x = new MyClass;
x[0,0] = 0;
x[0,1] = 7;
По поводу второго, как реализовать индексаторы, я, всё-таки, знаю. Мне хотелось, чтобы можно было писать конструкции типа
MyClass x = new MyClass;
x.P[0,0] = 0;
x.P[0,1] = 7;
x.P[1,0] = 5; //А здесь будет, например, ошибка, т.к. проверяется, что первый индекс не должен быть больше второго
т.е. использовать как свойства, но иметь возможность получать доступ непосредственно к индексам, как у индексаторов
public class MyClass
{
int[,] points;
MyProperty prop;
public class MyProperty
{
private MyClass c;
public MyProperty(MyClass c)
{
this.c = c;
}
public int this[int i, int j]
{
set
{
if (i > j) throw new IndexOutOfRangeException;
c.points[i,j] = value; // приватное поле points доступно из этого класса, т.к. он -- внутренний
}
}
}
public MyClass
{
points = new int[5,5];
prop = new MyProperty(this);
}
public MyProperty P
{
get
{
return prop;
}
}
}
Немного извратно, конечно. Но другого способа получить контроль над индексами так сразу не вижу. =/
public class MyClass
{
int[,] points;
public class MyProperty
{
private MyClass c;
public MyProperty(MyClass c)
{
this.c = c;
}
public int this[int i, int j]
{
set
{
if (i > j) throw new IndexOutOfRangeException;
c.points[i,j] = value; // приватное поле points доступно из этого класса, т.к. он -- внутренний
}
}
}
public MyProperty P
{
get
{
return new MyProperty(this);
}
}
}
x.P[1,0] = 5; //А здесь будет, например, ошибка, т.к. проверяется, что первый индекс не должен быть больше второгооператор [] применяется к типу свойства P, поэтому, если хочешь такое, делаешь свой тип (класс) с индексером и свойство P объявляешь этого типа.
Ну да, собсно это я и написал постом выше.
Немного извратно, конечно. Но другого способа получить контроль над индексами так сразу не вижу. =/делать MyProperty внутренним классом, особого смысла нет.
int[,] points — стоит инкапсулировать в MyProperty
Все остальные методы/свойства массива тупо делегируются к int[,] points
Короче стандартный прием обертки.
Ну да, собсно это я и написал постом выше.когда я писал пост, мне позвонили, поэтому я увидел твои посты уже позже
делать MyProperty внутренним классом, особого смысла нет.Смысл в том, что если класс определяется исключительно для нужд другого класса (как в этом примере) и не будет использоваться независимо от него, то правильнее делать его внутренним.
int[,] points — стоит инкапсулировать в MyPropertyДа, правильно.
нужно это за тем же, зачем и индексатор, но индексатор-то у класса может быть только один
у меня тоже был только вариант с индексатором на класс свойства, но думал, что можно проще
в общем, благодарю
нужно это за тем же, зачем и индексатор, но индексатор-то у класса может быть только одинперегруженных может быть несколько.
А может просто метод завести?
и там должны быть однотипные - несколько двумерных
Оставить комментарий
Serpent555
Допустим, есть свойство типачто именно происходит в момент выполнения присваивания типа Points[i, j] = point? В инете толком ничего не нашел, в книжке своей тоже, калечный мсдн вообще ничего умного как всегда не говорит. Варианты:
1) Берется get'ом временный массив, в нём правится элемент [i, j], затем запихивается set'ом на место. Логично, но очень некрасиво и медленно.
2) Присваивается непосредственно элемент [i, j]. Быстро, но очень нелогично. Ведь в методе set явно прописано присваивание именно массивов.
Таким образом, первый вопрос: как это работает?
Далее, пусть мне хочется сделать свойство, которое работало бы как индексатор, т.е. были бы доступны именно указанные при вызове индексы (например, для эмуляции непрямоугольного поля):
Так что второй вопрос звучит так: как это сделать?
Спасибо, жду комментариев.