Свойства и out
От: Аноним  
Дата: 15.11.10 15:18
Оценка:
В классе есть автосвойство (по имени SourceColumn), заведенное для того, чтобы get и set обладали разным уровнем видимости (public и private соответственно). Иначе использовалось бы поле.

public string SourceColumn
{
    get;
    private set;
}


Кроме него есть и второе автосвойство — TargetColumn. Оба свойства задаются одним и тем же алгоритмом, только разные входные параметры. Поэтому (во избежание copy-paste) для инициализации предусмотрен статический метод

private static bool Init(string data, out string column);


Свойство, однако, нельзя передать для инициализации. Сейчас используется такой код:

string sourceColumn;
Init(data, out sourceColumn);
SourceColumn = sourceColumn;


Как это сделать красивее? Можно автосвойство превратить в обычное свойство на host-поле, а передавать host, но заводить host только ради этого...

P.S. Почему компилятор не генерирует код, подобный используемому, автоматически, когда видит передачу свойства?
Re: Свойства и out
От: xobotik Россия  
Дата: 15.11.10 16:53
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>В классе есть автосвойство (по имени SourceColumn), заведенное для того, чтобы get и set обладали разным уровнем видимости (public и private соответственно). Иначе использовалось бы поле.


А>
А>public string SourceColumn
А>{
А>    get;
А>    private set;
А>}
А>


А>Кроме него есть и второе автосвойство — TargetColumn. Оба свойства задаются одним и тем же алгоритмом, только разные входные параметры.


С этого места поподробнее.

А>Поэтому (во избежание copy-paste) для инициализации предусмотрен статический метод


А>
А>private static bool Init(string data, out string column);
А>


Не стоит делать инициализаторов свойств если свойство запрещено для записи.

А>Свойство, однако, нельзя передать для инициализации. Сейчас используется такой код:


Свойство нельзя =) Необходимо создать для начала экземпляр класса, затем только мы можем работать со свойством.

А>
А>string sourceColumn;
А>Init(data, out sourceColumn);
А>SourceColumn = sourceColumn;
А>


А>Как это сделать красивее? Можно автосвойство превратить в обычное свойство на host-поле, а передавать host, но заводить host только ради этого...


Какая цель использования свойства в вашем типе?

А>P.S. Почему компилятор не генерирует код, подобный используемому, автоматически, когда видит передачу свойства?


Передать свойство нельзя =) можно либо считать данные со свойства либо записать данные (и только при условии что заданы set или get).
С уважением!
Re[2]: Свойства и out
От: Аноним  
Дата: 16.11.10 08:22
Оценка: :)
Здравствуйте, xobotik, Вы писали:

X>Не стоит делать инициализаторов свойств если свойство запрещено для записи.


?

Свойство для того и запрещено для записи, чтобы класс мог инициализировать его значение сам, путем выполнения алгоритма, вызываемого, кстати говоря, из конструктора. А другие — никакими путями не могли. Что за азбука ООПостроения!

А>>Свойство, однако, нельзя передать для инициализации. Сейчас используется такой код:

X>Свойство нельзя =) Необходимо создать для начала экземпляр класса, затем только мы можем работать со свойством.

???

А>>
А>>string sourceColumn;
А>>Init(data, out sourceColumn);
А>>SourceColumn = sourceColumn;
А>>


А>>Как это сделать красивее? Можно автосвойство превратить в обычное свойство на host-поле, а передавать host, но заводить host только ради этого...

X>Какая цель использования свойства в вашем типе?

Ну какая может быть цель? Изнутри оно рассчитывается, снаружи доступно всем, кто имеет ссылки на объект.

Я имел в виду такой вариант:

public string SourceColumn
{
    get { return _SourceColumn; }
    private set { _SourceColumn = value; }
}

private string _SourceColumn = ""; // Лишний хост.

...
Init(data, out _SourceColumn); // Зато не надо лишних копирований.
...


Это самый лучший вариант, или можно еще красивее решить?

А>>P.S. Почему компилятор не генерирует код, подобный используемому, автоматически, когда видит передачу свойства?

X>Передать свойство нельзя =) можно либо считать данные со свойства либо записать данные (и только при условии что заданы set или get).

Вопрос был не об этом. Для автосвойства ведь хост неявно генерируется, так? Почему бы компилятору не заменять автосвойство этим имплиситным хостом, если, конечно, аксессор set нарисован? И так ведь ясно, что никаких проверок и пр. со стороны программиста нет.

Вообще, вопрос ширше (ширее), конечно. Если бы было можно к полям давать разный доступ на чтение и запись, то нахрен бы мне вообще сдались эти [авто]свойства (в данном случае).
Re[3]: Свойства и out
От: HowardLovekraft  
Дата: 16.11.10 08:39
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>Свойство для того и запрещено для записи, чтобы класс мог инициализировать его значение сам, путем выполнения алгоритма, вызываемого, кстати говоря, из конструктора. А другие — никакими путями не могли

А>Вообще, вопрос ширше (ширее), конечно. Если бы было можно к полям давать разный доступ на чтение и запись, то нахрен бы мне вообще сдались эти [авто]свойства (в данном случае)
Если очень хочется, напишите так, и будет вам счастье:
    public class MyClass
    {
        public readonly String SourceColumn;
        public readonly String TargetColumn;

        public MyClass()
        {
            Init("...", out SourceColumn);
            Init("...", out TargetColumn);
        }

        public void Init(String data, out String column)
        {
            column = "...";
        }
    }

Есть же, в конце концов, String.Empty или DBNull.Value.

А>>>P.S. Почему компилятор не генерирует код, подобный используемому, автоматически, когда видит передачу свойства?

По-моему, вы не понимаете сути свойств и назначение автосвойств.
Re: Свойства и out
От: Kalina9001  
Дата: 16.11.10 08:40
Оценка: +1
Здравствуйте, <Аноним>, Вы писали:

А>
А>private static bool Init(string data, out string column);
А>


А>Свойство, однако, нельзя передать для инициализации. Сейчас используется такой код:


А>
А>string sourceColumn;
А>Init(data, out sourceColumn);
А>SourceColumn = sourceColumn;
А>


А>Как это сделать красивее? Можно автосвойство превратить в обычное свойство на host-поле, а передавать host, но заводить host только ради этого...



Возвращать значение?
SourceColumn = Init(data);
... << RSDN@Home 1.2.0 alpha 4 rev. 1478>>
Re[2]: Свойства и out
От: Аноним  
Дата: 16.11.10 10:06
Оценка:
Здравствуйте, Kalina9001, Вы писали:

K>Возвращать значение?

K>
K>SourceColumn = Init(data);
K>


Для того, чтобы показать суть, я обрезал пример до одной пары свойств. А их несколько.

То есть, реально сигнатура примерно такая:

private static bool Init(string data1, string data2, string data3, out string column1, out string column2);


А используется так:

string sourceColumn1, sourceColumn2;
warning |= Init(sourceData1, sourceData2, sourceData3, out sourceColumn1, out sourceColumn2);
SourceColumn1 = sourceColumn1;
SourceColumn2 = sourceColumn2;
...
string targetColumn1, targetColumn2;
warning |= Init(targetData1, targetData2, targetData3, out targetColumn1, out targetColumn2);
TargetColumn1 = targetColumn1;
TargetColumn2 = targetColumn2;


Так что, увы. С хост-переменной это выглядит так:

warning |= Init(sourceData1, sourceData2, sourceData3, out _SourceColumn1, out _SourceColumn2);
...
warning |= Init(targetData1, targetData2, targetData3, out _TargetColumn1, out _TargetColumn2);
Re[4]: Свойства и out
От: Аноним  
Дата: 16.11.10 10:17
Оценка:
Здравствуйте, HowardLovekraft, Вы писали:

HL>Если очень хочется, напишите так, и будет вам счастье:

HL>
HL>    public class MyClass
HL>    {
HL>        public readonly String SourceColumn;
HL>        public readonly String TargetColumn;

HL>        public MyClass()
HL>        {
HL>            Init("...", out SourceColumn);
HL>            Init("...", out TargetColumn);
HL>        }
HL>    }
HL>


Решение с readonly-полями мне не нравится. Потому, что не сработает в случае two-stage creation. Да, в моем примере я дергаю Init в конструкторе, но так бывает не всегда (а ответ хотелось бы универсальный).

А>>Почему компилятор не генерирует код, подобный используемому, автоматически, когда видит передачу свойства?

HL>По-моему, вы не понимаете сути свойств и назначение автосвойств.

Давайте по существу, или вообще никак. Если я, человек, могу преобразовать подразумеваемый

string myproperty { get; set; }
...
Foo(out myproperty);


в

string myproperty { get; set; }
...
string bar;
Foo(out bar);
myproperty = bar;


что мешает сделать это частью языка? Есть варианты, когда оно не сработает или превратится в грабли?

P.S. Sinix'у привет. Его я узнаю по оценкам, даже если никнейм не увидел. It's your style.
Re[3]: Свойства и out
От: Kalina9001  
Дата: 16.11.10 11:13
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Для того, чтобы показать суть, я обрезал пример до одной пары свойств. А их несколько.


А>То есть, реально сигнатура примерно такая:


А>
А>private static bool Init(string data1, string data2, string data3, out string column1, out string column2);
А>


А>А используется так:


А>
А>string sourceColumn1, sourceColumn2;
А>warning |= Init(sourceData1, sourceData2, sourceData3, out sourceColumn1, out sourceColumn2);
А>SourceColumn1 = sourceColumn1;
А>SourceColumn2 = sourceColumn2;
А>...
А>string targetColumn1, targetColumn2;
А>warning |= Init(targetData1, targetData2, targetData3, out targetColumn1, out targetColumn2);
А>TargetColumn1 = targetColumn1;
А>TargetColumn2 = targetColumn2;
А>


А>Так что, увы. С хост-переменной это выглядит так:


А>
А>warning |= Init(sourceData1, sourceData2, sourceData3, out _SourceColumn1, out _SourceColumn2);
А>...
А>warning |= Init(targetData1, targetData2, targetData3, out _TargetColumn1, out _TargetColumn2);
А>


IMHO что то не так в консерватории. Два out параметра моветон
Но если хочется извратиться
class Foo
        {
            public int X { get; private set; }
            public int Y { get; private set; }
            public Foo()
            {
             
                Init(1,2, x => X=x, y => Y=y );
            }

            private static void Init(int data1, int data2, Action<int> a1, Action<int> a2)
            {
                a1(data1);
                a2(data2);
            }
        }

... << RSDN@Home 1.2.0 alpha 4 rev. 1478>>
Re[5]: Свойства и out
От: Sinix  
Дата: 16.11.10 11:38
Оценка:
Здравствуйте, Аноним, Вы писали:

А>P.S. Sinix'у привет. Его я узнаю по оценкам, даже если никнейм не увидел. It's your style.


Привет
Ну а как ещё реагировать? Вы изучите матчасть перед тем, как рассказывать о труЪ дизайне языка и общайтесь чуть поспокойней. Либо и дальше будете получать смайлы за изобретение "хост-переменных", заявление о ненужности свойств/readonly-полей и пёрлы вида

Свойство для того и запрещено для записи, чтобы класс мог инициализировать его значение сам, путем выполнения алгоритма, вызываемого, кстати говоря, из конструктора. А другие — никакими путями не могли. Что за азбука ООПостроения!

Заметьте, ничего личного — ляпы делают все.

А>что мешает сделать это частью языка? Есть варианты, когда оно не сработает или превратится в грабли?

Во-первых, вы стремитесь усложнить язык, чтобы сэкономить пару строчек в объявлении свойства.
Во-вторых, непонятно, почему out должен работать только для автосвойств и только внутри класса?
В-третьих, подобное сгоряча сделали для событий: при подписке внутри класса обращались к полю. Идиотизм починили (частично) только к 4му шарпу.
Re[4]: Свойства и out
От: Аноним  
Дата: 16.11.10 11:41
Оценка:
Здравствуйте, Kalina9001, Вы писали:

K>IMHO что то не так в консерватории. Два out параметра моветон


Они рассчитываются на основе результатов (дорогого) парсинга in-параметров. Которые (результаты) сами по себе не нужны нигде и никогда, а потому хранить их за пределами метода не хочется. Что в этом моветонного?

Для объединения их в одну сущность (возвращаемую методом) тоже нет достаточных оснований — используются они сугубо порознь.

K>Но если хочется извратиться


Прикольно, но не хочется
Re[6]: Свойства и out
От: Аноним  
Дата: 16.11.10 12:15
Оценка:
Здравствуйте, Sinix, Вы писали:

S>перед тем, как рассказывать о труЪ дизайне языка


Где это я рассказываю о дизайне (не знаю, что такое "труЪ")? Я задал вопрос, причем ожидал, что кто-то напишет, мол так сделать было нельзя потому-то и тому-то. То есть, я предполагал, что есть причины, по которым так не сделали, которых я не вижу. Если вы видите — напишите.

>Либо и дальше будете получать смайлы за изобретение "хост-переменных"


А как называется такая переменная, на которой свойство паразитирует, то есть _Property?

int Property
{
    get { return _Property; }
    set { _Property = value; }
}

int _Property;


Я такого термина не знаю. В MSDN'е они фигурируют как "anonymous backing field", но это на термин не тянет. Если вы знаете — напишите.

>заявление о ненужности свойств/readonly-полей


Это передергивание. Когда я написал про ненужность свойств, то специально уточнил: "в данном случае".
Про ненужность readonly-полей вы просто придумали, и приписали мне.

>и пёрлы вида

S>

S>Свойство для того и запрещено для записи, чтобы класс мог инициализировать его значение сам, путем выполнения алгоритма, вызываемого, кстати говоря, из конструктора. А другие — никакими путями не могли. Что за азбука ООПостроения!

S>Заметьте, ничего личного — ляпы делают все.

И? Что вам не понравилось?

***

Наконец пошел разговор по делу.

S>Во-первых, вы стремитесь усложнить язык, чтобы сэкономить пару строчек в объявлении свойства.


А зачем, по-вашему, вообще ввели автосвойства? Вот цитата из MSDN'а:

In C# 3.0 and later, auto-implemented properties make property-declaration more concise when no additional logic is required in the property accessors.


Вам перевести, что это значит?

S>Во-вторых, непонятно, почему out должен работать только для автосвойств и только внутри класса?


И мне непонятно. В самом деле, почему? А, Sinix? Не надо задавать МНЕ этот вопрос, ведь это вы додумали сами: "только для автосвойств и только внутри класса".

Что до меня, то я бы сделал неявную генерацию (второй раз для вас, эксклюзивно):

string bar;
Foo(out bar);
myproperty = bar;

, разрешенную для любых свойств (не только авто-), при соблюдении двух условий:

1. Наличие set.
2. Область видимости set позволяет генерировать такой код.

Например, для foo.Foo(bar.Bar), код был бы такой (тип возьмем string):

string bar_mangled;
foo.Foo(out bar_mangled);
Bar.bar = _mangledbar;


S>В-третьих, подобное сгоряча сделали для событий: при подписке внутри класса обращались к полю. Идиотизм починили (частично) только к 4му шарпу.


Честно ничего не понял. В чем подобие?
Re[5]: Свойства и out
От: Kalina9001  
Дата: 16.11.10 12:56
Оценка:
Здравствуйте, <Аноним>, Вы писали:

K>>IMHO что то не так в консерватории. Два out параметра моветон


А>Они рассчитываются на основе результатов (дорогого) парсинга in-параметров. Которые (результаты) сами по себе не нужны нигде и никогда, а потому хранить их за пределами метода не хочется. Что в этом моветонного?


Исключения к примеру, один параметер накормил, другой не успел.



А>Для объединения их в одну сущность (возвращаемую методом) тоже нет достаточных оснований — используются они сугубо порознь.


Может Tuple использовать?
... << RSDN@Home 1.2.0 alpha 4 rev. 1478>>
Re[7]: Свойства и out
От: Sinix  
Дата: 16.11.10 13:02
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Где это я рассказываю о дизайне (не знаю, что такое "труЪ")?

Почему бы компилятору не заменять автосвойство этим имплиситным хостом, если, конечно, аксессор set нарисован? И так ведь ясно, что никаких проверок и пр. со стороны программиста нет.

Если бы было можно к полям давать разный доступ на чтение и запись, то нахрен бы мне вообще сдались эти [авто]свойства (в данном случае).
...
Если я, человек, могу преобразовать подразумеваемый ... в ... что мешает сделать это частью языка?
...

?

>Я задал вопрос, причем ожидал, что кто-то напишет, мол так сделать было нельзя потому-то и тому-то. То есть, я предполагал, что есть причины, по которым так не сделали, которых я не вижу. Если вы видите — напишите.

Тут два ответа. Короткий — выгода от реализации этой фичей несопоставима со стоимостью её полноценной реализации. Для долгого ответа надо цитировать кучу постов Липперта

А>А как называется такая переменная, на которой свойство паразитирует, то есть _Property?

Для начала, не переменная, а поле. Русскоязычного названия не помню, из англоязычных встречается — auitoimplemented|compiler generated field.

int _Property;

Мелкое замечание. В шарпе принято использовать camelCasing для полей/параметров/переменных, и, по возможности, не использовать префиксов, в том числе и подчёркиваний.

А>Я такого термина не знаю. В MSDN'е они фигурируют как "anonymous backing field", но это на термин не тянет. Если вы знаете — напишите.

Тянет Просто не настолько часто их обсуждают, чтобы короткий термин придумывать.

>>заявление о ненужности свойств/readonly-полей

А>Это передергивание. Когда я написал про ненужность свойств, то специально уточнил: "в данном случае".
Угу, тут погорячился Тем не менее, пассаж про замену свойств полями порадовал

А>И? Что вам не понравилось?

1. Где вы видите "свойство запрещено для записи" У read-only property отсутствует сеттер.
2. "чтобы класс мог инициализировать его значение сам, путем выполнения алгоритма, вызываемого, кстати говоря, из конструктора". Компилятор должен детектить _настолько_ специфичные сценарии?
3. "Что за азбука ООПостроения". Сферическое ООП имеет весьма малое отношение к любому из языков. Аппелировать к трушности ООП/паттернов при обсуждении нюансов _конкретного_ языка слегка некорректно.




S>>Во-первых, вы стремитесь усложнить язык, чтобы сэкономить пару строчек в объявлении свойства.

А>А зачем, по-вашему, вообще ввели автосвойства?
Липперт тоже удивляется:

With C# 3.0, the theme was very clear: language-integrated query. Anything that did not directly support LINQ was immediately made lower priority. It is rather amazing to me that partial methods and auto-implemented properties got in at all; that they were relatively easy features to design, implement, test and document was what saved them.

Основная польза от них — быстро накодить кучу прототип-классов. Ну и очевидно, польза от них была сопоставима со стоимостью реализации.

S>>Во-вторых, непонятно, почему out должен работать только для автосвойств и только внутри класса?

А>И мне непонятно. В самом деле, почему?
http://stackoverflow.com/questions/529782/c-property-and-ref-parameter-why-no-sugar


А>Что до меня, то я бы сделал неявную генерацию

1. ref/out имеет весьма чёткую семантику, работает с pointer type и должен работать напрямую с backing field. Это важно для интеропа/interlocked операций.
2. Если метод изменил переданную ему ссылку и кинул исключение, поведение будет отличаться для полей и свойств.

S>>В-третьих, подобное сгоряча сделали для событий: при подписке внутри класса обращались к полю. Идиотизм починили (частично) только к 4му шарпу.


А>Честно ничего не понял. В чем подобие?

В неочевидности — почему код скопипастенный внутрь класса работает не так, как ожидалось.
Только недавно обсуждали:
http://rsdn.ru/forum/dotnet/4032018.flat.aspx
Автор: mihhon
Дата: 10.11.10
Re[8]: Свойства и out
От: Аноним  
Дата: 16.11.10 14:03
Оценка: :)
Здравствуйте, Sinix, Вы писали:

S>?


Цитируете вопросы, говорите, что это рассказ о дизайне. Я это даже обсуждать не хочу.

S>Тут два ответа. Короткий — выгода от реализации этой фичей несопоставима со стоимостью её полноценной реализации. Для долгого ответа надо цитировать кучу постов Липперта


Возьмем короткий ответ. Что такое "полноценная реализация" и как вы пришли к выводу, что "выгода несопоставима со стоимостью"?

А>>И? Что вам не понравилось?

S>1. Где вы видите "свойство запрещено для записи" У read-only property отсутствует сеттер.

Вот это вот

public string SourceColumn
{
    get;
    private set;
}


хоботик назвал "свойство запрещено для записи". Я бы так не назвал (как именно назвал я, вы можете посмотреть в исходном постинге), но раз он назвал, я его процитировал (в своем ответе ему).

S>2. "чтобы класс мог инициализировать его значение сам, путем выполнения алгоритма, вызываемого, кстати говоря, из конструктора". Компилятор должен детектить _настолько_ специфичные сценарии?


Короче, понял я все. Вы читаете с пятого на десятое.

Представьте себе, компилятор УЖЕ детектит "настолько специфичные сценарии". Он видит, что set помечен как private, и дает классу инициализировать значение самому, а другим классам не дает.

То, что вы цитируете, было ответом на вопрос хоботика "Какая цель использования свойства в вашем типе?". Именно свойство, а не поле используется для того, чтобы пользоваться мог кто угодно, а задавать значение — только сам класс.

Почему не использовать readonly-поле? — спросил после этого HowardLovekraft. Возможный переход к two-stage creation — ответил я.

S>3. "Что за азбука ООПостроения". Сферическое ООП имеет весьма малое отношение к любому из языков. Аппелировать к трушности ООП/паттернов при обсуждении нюансов _конкретного_ языка слегка некорректно.


Что такое "аппелировать к трушности" я не понимаю, и уверен, что не стоит оно того. В любом случае, дискутировать на эту тему не буду.

Азбукой я назвал использование разных областей видимости.

S>


S>>>Во-первых, вы стремитесь усложнить язык, чтобы сэкономить пару строчек в объявлении свойства.

А>>А зачем, по-вашему, вообще ввели автосвойства?
S> Липперт тоже удивляется:
S>

S>With C# 3.0, the theme was very clear: language-integrated query. Anything that did not directly support LINQ was immediately made lower priority. It is rather amazing to me that partial methods and auto-implemented properties got in at all; that they were relatively easy features to design, implement, test and document was what saved them.

S>Основная польза от них — быстро накодить кучу прототип-классов. Ну и очевидно, польза от них была сопоставима со стоимостью реализации.

Как вы лихо оцениваете "стоимость реализации", однако. Ну, да ладно. Объективных противопоказаний нет? Одна мифическая стоимость?

S>>>Во-вторых, непонятно, почему out должен работать только для автосвойств и только внутри класса?

А>>И мне непонятно. В самом деле, почему?
S>http://stackoverflow.com/questions/529782/c-property-and-ref-parameter-why-no-sugar

Вот за это спасибо. Я подозревал, что сразу туда надо отнести вопрос, а там уже есть, как оказалось. Почитав, уверился, что объективных противопоказаний нет. Никто ничего не противопоказал. Более того, тема популярная. Там на кодепроджект ссылка есть. Народ изобретает воркэраунды.

А>>Что до меня, то я бы сделал неявную генерацию

S>1. ref/out имеет весьма чёткую семантику, работает с pointer type и должен работать напрямую с backing field. Это важно для интеропа/interlocked операций.
S>2. Если метод изменил переданную ему ссылку и кинул исключение, поведение будет отличаться для полей и свойств.

Оно и сейчас отличается.
Re[6]: Свойства и out
От: Аноним  
Дата: 16.11.10 14:09
Оценка:
Здравствуйте, Kalina9001, Вы писали:

K>Исключения к примеру, один параметер накормил, другой не успел.


Отвечу в духе Путина — они ловятся.

Отсутствие любого из параметров делает дальнейшую работу невозможной anyway.

А>>Для объединения их в одну сущность (возвращаемую методом) тоже нет достаточных оснований — используются они сугубо порознь.


K>Может Tuple использовать?


А как они сделают код читаемее и проще?
Re[9]: Свойства и out
От: xobotik Россия  
Дата: 16.11.10 20:16
Оценка: +1 :)
Здравствуйте, Аноним, Вы писали:

Вы занимаетесь херней
С уважением!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.