匿名方法应按条件返回字符串

时间:2019-03-21 12:55:06

标签: c# properties switch-statement return anonymous-methods

我试图理解用C#编写匿名方法。 但是很难取得成功。

请查看我的示例。 我正在尝试通过给定条件填充名为Value的属性。

当我编写一个私有的helper方法时,该方法将一个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!";
            }
        }
    }
}

不幸的是编译器说:

  

Lambda表达式不能转换为字符串类型,因为它不是委托。

2 个答案:

答案 0 :(得分:3)

由于编译器解释此行而出现错误:

Value = y => {...}

作为作业。它认为您想将lambda表达式分配给Value。但是类型不匹配! Valuestring,而不是任何类型的委托。有关详细信息,请参见Compiler Error CS1660

您真正想要的是执行此lambda并分配结果值。为此,您可以使用Func<string>在创建lambda时定义委托和返回值。然后使用( )括号立即执行它,就像在常规方法调用中一样:

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!
    };

突然间,这些东西变得可编译了。

编辑:

显然,编译器无法推断返回类型,因此无法自行指定委托类型。此示例可以说明:

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

此行导致错误:

  

CS0815无法将lambda表达式分配给隐式类型的变量

但是委托类型的明确指定可以解决此错误:

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

这表明委托类型的显式规范是必要且必要的。

答案 1 :(得分:2)

您正在尝试执行的操作在C#中尚不可用(因为尚未将switch语句明确地评估为一个返回值)。这样做的原因是切换条件可能包含任意代码,而不仅仅是一个表达式。

将有new way的C#8编写switch语句使您的代码成为可能。

您可以通过创建辅助方法来解决问题:

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!";
    }
}

并且辅助方法可以是local function

如果您仍然真的希望内联字符串映射,则可以嵌套三元运算符。

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#将能够明确评估结果,这使编译器感到满意。

您还可以通过将description attributes添加到enum

来解决问题。