Условное утверждение, общий делегат ненужного приведения - PullRequest
8 голосов
/ 16 августа 2011

У меня действительно странная проблема с условным оператором при установке значения Action<T>.Дело не в том, что я не знаю, как обойти это, так как это довольно легко решить, используя обычный if.

Вот моя проблема:

public class Test
{
    public bool Foo { get; set; }
    public Action<bool> Action { get; set; }

    public void A()
    {
        Action = Foo ? B : C;//Gives compiler error
    }

    public void B(bool value)
    {

    }

    public void C(bool value)
    {

    }
}

Это дает мнеошибка компилятора с сообщением

Не существует явного преобразования между «группой методов» и «группой методов».

Что странно, поскольку я не могу понять, почему этобудет недопустимым.

Кстати, приведенный ниже синтаксис сделает это допустимым (с точки зрения компиляторов):

    public void A()
    {
        Action = Foo ? (Action<bool>) B : C;
    }

Так что, возможно, вы можете прочитать вопрос как, почемуактёрский состав необходим?

Ответы [ 4 ]

2 голосов
/ 16 августа 2011

Вы объединяете две схожие концепции:

A) Группа методов.Группа методов - это один или несколько методов C # с одинаковыми именами.Это абстракция, используемая главным образом компилятором;Вы не можете обойти группу методов.Все, что вы можете сделать с группой методов, это вызвать ее или создать из нее делегата.Вы можете неявно создать делегата из группы методов, если сигнатуры типов совпадают.

B) Делегат.Вы знаете, что такое делегат;он имеет особую сигнатуру типа и ссылается непосредственно на метод.Наряду с его вызовом вы можете передать его и обработать как объект первого класса.

Так что в первом примере ваше выражение возвращает группу методов B с одной стороны и другую группу методовC на другой стороне.Тернарный оператор должен возвращать один и тот же тип с обеих сторон, но он не знает, к чему приводить обе стороны;тип переменной, которой вы присвоили результат (Action<bool>), не определяет тип выражения.Так что это неоднозначно.

Во втором примере вы законно приводите группу методов B к делегату Action<bool> с одной стороны троичного оператора.В процессе устранения неоднозначности выражения компилятор пытается привести каждую сторону к типу другой стороны.Он может успешно привести группу методов C к Action<bool>, поэтому он делает это, и выражение является допустимым.

1 голос
/ 16 августа 2011

Потому что B и C на самом деле не являются делегатами. Это группы методов, и они могут быть косвенно преобразованы в делегаты (в частности, Action<bool>), но это не одно и то же.

Тип условного выражения должен быть согласованным в обеих ветвях, и поскольку B и C в настоящее время являются группами методов (которые не являются типизированными), компилятор не может определить, каким должен быть тип. Как говорится, между ними нет явного преобразования.

Кроме того, он не может (или, по крайней мере, не ) просмотреть другую сторону оператора присваивания и сказать: «О, это должно быть * 1014». *».

Когда вы добавляете приведение, тип выражения левой ветви становится Action<bool>, и там равно неявному преобразованию между группой методов на другой стороне и этим делегатом, так что компилятор счастлив еще раз: тип всего выражения: Action<bool>.

0 голосов
/ 16 августа 2011

Я думаю, Эрик снова скажет мне, что мои рассуждения немного неверны , но я все равно попробую и надеюсь на его исправление: -)

Группа методовнапример, B, не имеет типа, это не объект (B.GetType() не собирается компилироваться).
Его можно легко преобразовать в тип, поэтому существует неявное приведение,Пример:

Action<bool> a = B; // implicit cast taking place.

Однако, как видно из связанного вопроса, троичное выражение пытается найти тип возвращаемого значения, которому соответствуют обе части выражения.Он не знает, что позже должно произойти преобразование в Action<bool>.Поскольку группы методов сами по себе не являются типами, между ними нет преобразования, и B нельзя преобразовать в C, и поэтому компилятор жалуется именно на это.

Путем приведения любой из частейтроичного выражения в Action<bool>, вы говорите компилятору, что тип возвращаемого значения должен быть этим типом, и он проверяет, поддерживает ли другая часть троичного выражения неявное приведение к этому типу.Поскольку это так, код скомпилируется.

0 голосов
/ 16 августа 2011

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

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