"dynamic" 具有构建器模式的关键字隐藏了扩展方法
"dynamic" keyword with builder pattern hides extension method
我最近在测试某些东西时遇到了 dynamic
关键字的奇怪行为。这不是我迫切需要解决的问题,因为我只是在试验,但我想知道是否有人可以阐明正在发生的事情
我有一个构建器,它 return 是一个 HttpWebRequest
对象和 HttpWebRequest
上的一个扩展方法。
我的一个构建器方法采用 string
参数。当我向构建器方法传递一个字符串时,整个过程都有效,但我向它传递了一个 dynamic
变量,这是一个不再有效的字符串。
似乎应该 return 键入 HttpWebRequestBuilder
的构建器方法现在 returns 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
对象的工作方式有些奇怪。但任何解释将不胜感激。
发生这种情况是因为传递 dynamic
参数会使 C# 编译器将表达式的 return 类型,即 .SetBody(dynamicString)
,视为 dynamic
(相关的 explanation of method return types with dynamic parameters).
扩展方法仅作为常规方法与 dynamic
对象一起使用,而不是作为扩展方法(请参阅 Eric Lippert's answer 了解对此的解释),因此您会看到编译时错误。
虽然 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);
}
}
我最近在测试某些东西时遇到了 dynamic
关键字的奇怪行为。这不是我迫切需要解决的问题,因为我只是在试验,但我想知道是否有人可以阐明正在发生的事情
我有一个构建器,它 return 是一个 HttpWebRequest
对象和 HttpWebRequest
上的一个扩展方法。
我的一个构建器方法采用 string
参数。当我向构建器方法传递一个字符串时,整个过程都有效,但我向它传递了一个 dynamic
变量,这是一个不再有效的字符串。
似乎应该 return 键入 HttpWebRequestBuilder
的构建器方法现在 returns 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
对象的工作方式有些奇怪。但任何解释将不胜感激。
发生这种情况是因为传递 dynamic
参数会使 C# 编译器将表达式的 return 类型,即 .SetBody(dynamicString)
,视为 dynamic
(相关的 explanation of method return types with dynamic parameters).
扩展方法仅作为常规方法与 dynamic
对象一起使用,而不是作为扩展方法(请参阅 Eric Lippert's answer 了解对此的解释),因此您会看到编译时错误。
虽然 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);
}
}