在我测试某些内容时,我最近遇到了dynamic
关键字的奇怪行为。这不是我迫切需要解决的问题,因为我只是在尝试,但我想知道是否有人可以对发生的事情有所了解
我有一个构建器,它在HttpWebRequest
上返回一个HttpWebRequest
对象和一个扩展方法。
我的一个构建器方法采用string
参数。当我将构建器方法传递给字符串时,整个过程都有效,但是我传递了一个dynamic
变量,这是一个不再有效的字符串。
似乎返回类型HttpWebRequestBuilder
的构建器方法现在返回dynamic
。
下面的代码很简单,可以重现它,也可以使用here
注意
要使其有效,请注释掉.SetBody(dynamicString)
行并取消注释.SetBody(json)
行。
public class Program
{
public static void Main()
{
dynamic dynamicString = "{ \"test\" : \"value\" }";
string json = "{ \"test\" : \"value\" }";
string test = new HttpWebRequestBuilder()
.SetRequestType()
//.SetBody(json) //uncomment this and it works
.SetBody(dynamicString) //uncomment this and it breaks
.Build()
.ExtensionMethod();
Console.WriteLine(test);
}
}
public class HttpWebRequestBuilder
{
private readonly HttpWebRequest _request;
public HttpWebRequestBuilder()
{
Uri uri = new Uri("http://www.google.com");
_request = WebRequest.CreateHttp(uri);
}
public HttpWebRequestBuilder SetRequestType()
{
_request.Method = "POST";
_request.ContentType = "application/json";
return this;
}
public HttpWebRequestBuilder SetBody(string json)
{
byte[] bytes = Encoding.UTF8.GetBytes(json);
_request.ContentLength = bytes.Length;
using (Stream writer = _request.GetRequestStream())
{
writer.Write(bytes, 0, bytes.Length);
writer.Flush();
}
return this;
}
public HttpWebRequest Build()
{
return _request;
}
}
public static class WebRequestExtensions
{
public static string ExtensionMethod(this HttpWebRequest webRequest)
{
return "extension method worked";
}
}
我猜这是dynamic
个对象工作方式的奇怪之处。但任何解释都会非常感激。
答案 0 :(得分:7)
这是因为传递dynamic
参数会使C#编译器将表达式的返回类型(即.SetBody(dynamicString)
)视为dynamic
(相关explanation of method return types with dynamic parameters)。
扩展方法只能作为常规方法使用dynamic
个对象,而不是扩展方法(请参阅Eric Lippert's answer以获得解释),因此会看到编译时错误。
答案 1 :(得分:1)
尽管dasblinkenlight的答案似乎是正确的,但请记住,您可以通过以下方式重新编写代码来避免此问题:
public class Program
{ public static void Main()
{
dynamic dynamicString = "{ \"test\" : \"value\" }";
string json = "{ \"test\" : \"value\" }";
var test = new HttpWebRequestBuilder();
test.SetRequestType();
//test.SetBody(json); //still works
test.SetBody(dynamicString); // works also now
var b = test.Build();
var s = b.ExtensionMethod();
Console.WriteLine(s);
}
}