我试图理解在C#中编写匿名方法。但难以取得成功。
请看看我的例子。我正在尝试通过给定条件填充名为Value的属性。
当我写一个私有帮助器方法,它接受一个inputparam int lockCardStatus并返回一个解决方案的字符串,但我的意图是尝试使用“quickshot”,如下所示:
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 Expression无法转换为类型字符串,因为它不是委托。
出现错误是因为编译器解释了这一行:
Value = y => {...}
作为一项任务。它认为你想将lambda表达式赋给Value
。但类型不匹配! Value
是一个string
而不是任何形式的代表。有关详细信息,请参阅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";});
这表明委托类型的显式规范是必要且必不可少的。
您尝试做的事情在C#中不可用(因为)无法将switch语句明确地评估为一个返回值。原因是switch case可能包含任意代码而不只是一个表达式。
在C#8中将有一个new way编写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
来解决您的问题