为什么这个string.Format()方法返回的是dynamic类型而不是string类型?

12
@{
    ViewBag.Username = "Charlie Brown";
    string title1 = string.Format("Welcome {0}", ViewBag.Username);
    var title2 = string.Format("Welcome {0}", ViewBag.Username);
}
在MVC视图中,我像这样使用这些值:
@Html.ActionLink(title1, "Index")
@Html.ActionLink(title2, "Index")

这里,title1 可以正常工作。但是 title2 的 ActionLink 因编译错误而失败:

CS1973:“System.Web.Mvc.HtmlHelper”没有适用的方法名为“StandardHeader”,但似乎有一个同名的扩展方法。扩展方法无法动态调度。请考虑对动态参数进行强制转换或在不使用扩展方法语法调用扩展方法。

string.Format() 有很多重载,但返回类型始终为string。为什么在使用 var 进行变量声明时会失败?


16
我怀疑你所提供的代码并不会导致出现这个错误消息,我猜测是其他一段代码导致了这个问题。 - Jon Skeet
3个回答

16

好的,我们已经从评论和其他答案中知道问题出在 dynamic 上。由于 dynamic 是在运行时绑定的,只有在那个时候才进行重载决议和类型验证。

因此:如果至少有一个参数是 dynamic,则重载决议将在运行时进行。

这就是为什么允许这个明显的错误:

dynamic x = "";
int i = string.Format("{0}", x);

如果没有返回一个 intstring.Format 重载,这并不影响。它会稍后评估。


4
所有表达式都在运行时计算,但有时会有一些编译时字面常量的操作例外。这并不特定于dynamic。这里被延迟的是重载解析,表达式的类型是在运行时确定的。这是不同的。 - Servy
好的,这就解释了。谢谢。 - Blaise
1
@Servy 在 int i = x; 中没有重载决议,但它仍然可以编译。你对此有什么想法?(从你的评论中我理解它不应该工作,或者我读错了吗?) - Patrick Hofman
1
@PatrickHofman dynamic 可以隐式转换为任何类型。 - Servy
现在我已经搞清楚了,我已更新答案。感谢@CodeCaster。 - Patrick Hofman
显示剩余4条评论

11
错误信息告诉您这里出了什么问题:

扩展方法无法动态调度。请考虑将动态参数转换为静态类型或在不使用扩展方法语法的情况下调用扩展方法。

title2 的类型是 dynamic。 您需要将其转换为 string,因为您知道它是什么。


9
如果ViewBag.Username是动态的,那么它将是“dynamic”类型。 “dynamic”类型适用于整个表达式。 - Lee
3
如果任何一个参数是 dynamic,那么每个方法都可以返回 dynamic - Servy
7
这里值得解释一下为什么 title2 的类型是 dynamic。我认为,李的解释是这个问题的关键点。 - Jon Skeet
2
@Servy: 挑剔一下:如果参数是动态的。将参数类型设置为“dynamic”没有任何影响。 - Jon Skeet
@Servy,string.Format() 方法的返回类型不算在内吗? - Blaise
显示剩余5条评论

7

这是一个动态的视图包(ViewBag)。 enter image description here

如果您使用实际的用户名(而不是ViewBag.UserName),它将起作用。 或者将(string)ViewBag.Username强制转换为字符串。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接