Анонимный метод должен возвращать строку по условию - PullRequest
1 голос
/ 21 марта 2019

Я пытаюсь понять написание анонимных методов в C #. Но возникают проблемы, чтобы добиться успеха.

Пожалуйста, посмотрите на мой пример. Я пытаюсь заполнить свойство с именем Value заданными условиями.

Когда я напишу приватный вспомогательный метод, который принимает inputparam int lockCardStatus и возвращает строку, которая будет решением, но я собираюсь попробовать это с «быстрой стрельбой», например так:

MailMessageTextPlaceholders = new List<MailMessageTextPlaceholder>
{
    new MailMessageTextPlaceholder
    {
        PlaceholderName = "status",
        Value = y => 
        {
            switch (_lockCard.Status)
            {
                case (int)LockCard.LockCardStatus.Done :
                    return "Is Done";
                case (int)LockCard.LockCardStatus.Pending :
                    return "Is in Pending status";
                case (int)LockCard.LockCardStatus.Open :
                    return "Has been created";
                default:
                    return "No status yet!";
            }
        }
    }
}

К сожалению, компилятор говорит:

Лямбда-выражение не может быть преобразовано в строку типа, потому что оно не является delgate.

Ответы [ 2 ]

3 голосов
/ 21 марта 2019

Ошибка возникает из-за того, что компилятор интерпретирует эту строку:

Value = y => {...}

как назначение. Он думает, что вы хотите присвоить лямбда-выражение Value. Но типы не совпадают! Value является string и не является делегатом любого рода. Для получения подробной информации см. Ошибка компилятора CS1660

Что вы действительно хотите, так это выполнить эту лямбду и присвоить полученное значение. Для этого вы можете определить делегат и возвращаемое значение при создании лямбды, используя Func<string>. и выполнить его на месте, используя ( ) скобки, как в обычном вызове метода:

MailMessageTextPlaceholder hodler = new MailMessageTextPlaceholder()
    {
        Value = new Func<string>(() =>
        {
            switch (_lockCard.Status)
            {
                case (int)LockCard.LockCardStatus.Done:
                    return "Is Done";
                case (int)LockCard.LockCardStatus.Pending:
                    return "Is in Pending status";
                case (int)LockCard.LockCardStatus.Open:
                    return "Has been created";
                default:
                    return "No status yet!";
            }
        })() // <- this executes the method!
    };

И вдруг этот материал становится компилируемым.

EDIT:

Видимо, компилятор не может определить тип возвращаемого значения и, таким образом, сам указать тип делегата. Это можно проиллюстрировать на этом примере:

var asd = () => { return "XXX"; };

Эта строка приводит к ошибке:

CS0815 Невозможно назначить лямбда-выражение для неявно типизированной переменной

Но явная спецификация типа делегата устраняет эту ошибку:

var asd = new Func<string>(() => { return "XXX";});

Это указывает на то, что явное указание типа делегата является необходимым и необходимым.

2 голосов
/ 21 марта 2019

То, что вы пытаетесь сделать, недоступно (пока) в C #, поскольку операторы switch нельзя однозначно оценить для одного возвращаемого значения.Причина этого заключается в том, что случаи переключения могут содержать любой произвольный код, а не только одно выражение.

Будет новый способ написания операторов переключения в C # 8, который сделает ваш код возможным.

Вы можете решить свою проблему, создав вспомогательный метод:

MailMessageTextPlaceholders = new List<MailMessageTextPlaceholder>
{
    new MailMessageTextPlaceholder
    {
        PlaceholderName = "status",
        Value = GetStatusDescription(_lockCard.Status)
    }
}

string GetStatusDescription(LockCard.LockCardStatus status)
{
     switch (status)
     {
        case (int)LockCard.LockCardStatus.Done :
             return "Is Done";
        case (int)LockCard.LockCardStatus.Pending :
             return "Is in Pending status";
        case (int)LockCard.LockCardStatus.Open :
              return "Has been created";
        default:
              return "No status yet!";
    }
}

, а вспомогательный метод может быть локальной функцией

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

MailMessageTextPlaceholders = new List<MailMessageTextPlaceholder>
{
    new MailMessageTextPlaceholder
    {
        PlaceholderName = "status",
        Value = 
           status == LockCard.LockCardStatus.Done
               ? "Is Done";
               : status == LockCard.LockCardStatus.Pending 
                  ? "Is in Pending status"
                  : status == LockCard.LockCardStatus.Open 
                      ? "Has been created"
                      : "No status yet!";
    }
}

Когда вы используете троичные операторы, C # сможет однозначно оценить результат, что делает компилятор счастливым.

Вы также можете решить свою проблему, добавив атрибуты описания к вашему enum

...