Лямбда и модификаторы параметра (ref/out)
От: _FRED_ Черногория
Дата: 22.06.11 06:57
Оценка: 9 (1)
Почему модификаторы ref/out можно указывать только в explicit-anonymous-function-parameter, то есть обязательно совместно с типом?

private delegate bool TryParse<T>(string text, out T result);
// Так можно
TryParse<int> parse1 = (string text, out int result) => Int32.TryParse(text, out result);
// А так нет?
TryParse<int> parse2 = (text, out result) => Int32.TryParse(text, out result);


Help will always be given at Hogwarts to those who ask for it.
Отредактировано 31.01.2024 13:25 _FRED_ . Предыдущая версия .
Re: Лямбда и моджификаторы параметра (ref/out)
От: Lloyd Россия  
Дата: 22.06.11 07:08
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Почему модификаторы ref/out можно указывать только в explicit-anonymous-function-parameter, то есть обязательно совместно с типом?


Может потому, что возникает непоределенность с тем, что out может трактоваться на объявление типа?
Re[2]: Лямбда и моджификаторы параметра (ref/out)
От: _FRED_ Черногория
Дата: 22.06.11 07:17
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>Здравствуйте, _FRED_, Вы писали:


_FR>>Почему модификаторы ref/out можно указывать только в explicit-anonymous-function-parameter, то есть обязательно совместно с типом?


L>Может потому, что возникает непоределенность с тем, что out может трактоваться на объявление типа?


Тут у них в документации какая-то каша: тут оно в таблице ключевых слов, а тут уже сказано "contextual keyword", хотя если пойти дальше по ссылкам, оно снова называется "keyword".

Как бы там нибыло, в данный момент нельзя использовать имя "out" без "@".
Help will always be given at Hogwarts to those who ask for it.
Re: Лямбда и моджификаторы параметра (ref/out)
От: Пельмешко Россия blog
Дата: 22.06.11 10:52
Оценка: 1 (1)
Здравствуйте, _FRED_, Вы писали:

_FR>Почему модификаторы ref/out можно указывать только в explicit-anonymous-function-parameter, то есть обязательно совместно с типом?


_FR>
_FR>private delegate bool TryParse<T>(string text, out T result);
_FR>// Так можно
_FR>TryParse<int> parse1 = (string text, out int result) => Int32.TryParse(text, out result);
_FR>// А так нет?
_FR>TryParse<int> parse2 = (text, out result) => Int32.TryParse(text, out result);
_FR>


_FR>


[имхо]
Типы неявно типизированных параметров выводятся двумя способами — по сигнатуре типа делегата, к которому приводится лямбда-выражение, а в случае нескольких перегрузок (а значит нескольких сигнатур, как в Enumerable.*) — по телу лямбда-выражения. Так вот, в C# невозможно отличить usage ref-параметра от обычного (а вот в F# — можно), поэтому второй способ вывода типов невозможен. То есть в случае таких делегатов C# уже не сможет вывести корректный тип по телу лямбды:
delegate int Foo(int x);
delegate int Bar(ref int x);
x => { ... } // что это?

Мне кажется, что C# team всё же посчитали, что ref/out-модификаторы являются именно частью типа, а так как вывод ref/out-типов иногда вовсе невозможен, то просто запретили ref/out в случае неявно типизированных параметров, а не сделали "не-совсем-неявно-типизированных" параметров, о которых ты говоришь.
[/имхо]
Re[2]: Лямбда и моджификаторы параметра (ref/out)
От: _FRED_ Черногория
Дата: 23.06.11 03:52
Оценка:
Здравствуйте, Пельмешко, Вы писали:

_FR>>Почему модификаторы ref/out можно указывать только в explicit-anonymous-function-parameter, то есть обязательно совместно с типом?

_FR>>private delegate bool TryParse<T>(string text, out T result);
_FR>>// Так можно
_FR>>TryParse<int> parse1 = (string text, out int result) => Int32.TryParse(text, out result);
_FR>>// А так нет?
_FR>>TryParse<int> parse2 = (text, out result) => Int32.TryParse(text, out result);

_FR>>

П>[имхо]

П>Типы неявно типизированных параметров выводятся двумя способами — по сигнатуре типа делегата, к которому приводится лямбда-выражение, а в случае нескольких перегрузок (а значит нескольких сигнатур, как в Enumerable.*) — по телу лямбда-выражения. Так вот, в C# невозможно отличить usage ref-параметра от обычного (а вот в F# — можно), поэтому второй способ вывода типов невозможен. То есть в случае таких делегатов C# уже не сможет вывести корректный тип по телу лямбды:
П>delegate int Foo(int x);
П>delegate int Bar(ref int x);
П>x => { ... } // что это?


Можно посмотреть законченный пример использования? Так как не совсем понятно о чём именно речь: неоднозначностей и без модификаторов хватает:
delegate int Foo(int x);
delegate int Boo(int x);
x => { ... } // что это?


П>Мне кажется, что C# team всё же посчитали, что ref/out-модификаторы являются именно частью типа, а так как вывод ref/out-типов иногда вовсе невозможен, то просто запретили ref/out в случае неявно типизированных параметров, а не сделали "не-совсем-неявно-типизированных" параметров, о которых ты говоришь.

П>[/имхо]

Частью типа модификаторы и по сути являются, добавляя ссылку Но: вывод и обычных параметров _не всегда_ возможен, однако его сделали, ибо _во многих_ случаях он всё-таки возможен.
Help will always be given at Hogwarts to those who ask for it.
Re[2]: Лямбда и моджификаторы параметра (ref/out)
От: Алексей.  
Дата: 23.06.11 07:58
Оценка: -1
Здравствуйте, Пельмешко, Вы писали:

П>Типы неявно типизированных параметров выводятся двумя способами — по сигнатуре типа делегата, к которому приводится лямбда-выражение,


Это верно.

П>а в случае нескольких перегрузок (а значит нескольких сигнатур, как в Enumerable.*) — по телу лямбда-выражения.


А вот это нет. Если лямбда может быть сконвертирована более чем в один делегат, то возникает неоднозначность и ошибка компиляции.
По коду тела лямбда-выражения выводится только возвращаемый лямбдой тип (при помощи вывода типов return выражений).

П>Так вот, в C# невозможно отличить usage ref-параметра от обычного (а вот в F# — можно), поэтому второй способ вывода типов невозможен.


Вывод возможен, но только по сигнатуре делегата, а не по использованию.

П>Мне кажется, что C# team всё же посчитали, что ref/out-модификаторы являются именно частью типа, а так как вывод ref/out-типов иногда вовсе невозможен, то просто запретили ref/out в случае неявно типизированных параметров, а не сделали "не-совсем-неявно-типизированных" параметров, о которых ты говоришь.


Возможно что C# team решила что пользы от вывода out параметра по сигнатуре делегата нет.
Re[3]: Лямбда и моджификаторы параметра (ref/out)
От: _FRED_ Черногория
Дата: 23.06.11 09:47
Оценка:
Здравствуйте, Алексей., Вы писали:

П>>а в случае нескольких перегрузок (а значит нескольких сигнатур, как в Enumerable.*) — по телу лямбда-выражения.


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

А>По коду тела лямбда-выражения выводится только возвращаемый лямбдой тип (при помощи вывода типов return выражений).

Имеется в виду этот вот сценарий:
    static void Main()
    {
        M(x => x + 1 > 0); // 1
        M(x => !String.IsNullOrEmpty(x)); // 2
    }

    static void M(Func<int, bool> action) { Console.WriteLine(1); }
    static void M(Func<string, bool> action) { Console.WriteLine(2); }
    static void M(Func<object, bool> action) { Console.WriteLine(3); }
Help will always be given at Hogwarts to those who ask for it.
Re[4]: Лямбда и моджификаторы параметра (ref/out)
От: Алексей.  
Дата: 23.06.11 11:00
Оценка:
Да, здесь неоднозначности не возникает т.к. лямбда может быть сконвертирована только в один из делегатов.

Говоря о неоднозначности я подразумевал вот такой вариант:
static void Main()
{
    M(x => x + 1 > 0); // ambiguous
}

static void M(Func<int, bool> action) { Console.WriteLine(1); }
static void M(Func<long, bool> action) { Console.WriteLine(2); }
Re[5]: Лямбда и моджификаторы параметра (ref/out)
От: _FRED_ Черногория
Дата: 23.06.11 11:19
Оценка:
Здравствуйте, Алексей., Вы писали:

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

А>Говоря о неоднозначности я подразумевал вот такой вариант:

Ну так я лишь показал, что "По коду тела лямбда-выражения выводится только возвращаемый лямбдой тип (при помощи вывода типов return выражений)." неверно. А то, что этот вывод, как и многие другие, в некоторых случаях не срабатывает — вполне очевидные факт.
Help will always be given at Hogwarts to those who ask for it.
Re[6]: Лямбда и моджификаторы параметра (ref/out)
От: Алексей.  
Дата: 23.06.11 11:29
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Ну так я лишь показал, что "По коду тела лямбда-выражения выводится только возвращаемый лямбдой тип (при помощи вывода типов return выражений)." неверно.


Каким образом?

В приведенных примерах осуществляется перебор методов (в алгоритме overload resolution) и как следствие делегатов (т.к. они являются параметрами методов) и попытка привести лямбду у одному из них. Приведение является допустимым только для одного из делегатов. И метод с этим делегатом выбирается. Вывода типов тут нет.
Re[7]: Лямбда и моджификаторы параметра (ref/out)
От: _FRED_ Черногория
Дата: 23.06.11 12:00
Оценка:
Здравствуйте, Алексей., Вы писали:

_FR>>Ну так я лишь показал, что "По коду тела лямбда-выражения выводится только возвращаемый лямбдой тип (при помощи вывода типов return выражений)." неверно.

А>Каким образом?

А>В приведенных примерах осуществляется перебор методов (в алгоритме overload resolution) и как следствие делегатов (т.к. они являются параметрами методов) и попытка привести лямбду у одному из них. Приведение является допустимым только для одного из делегатов. И метод с этим делегатом выбирается. Вывода типов тут нет.


С тем же успехом, если использовать вашу точку зрения, можно утверждать, что и в следующем примере:

    static void Main()
    {
        M(x => x + 1 > 0); // 1
    }

    static void M(Func<int, bool> action) { Console.WriteLine(1); }


Вывода типов нет
Help will always be given at Hogwarts to those who ask for it.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.