Moo*_*eef 13 c# struct class implicit-conversion
有问题的结构/类:
public struct HttpMethod
{
public static readonly HttpMethod Get = new HttpMethod("GET");
public static readonly HttpMethod Post = new HttpMethod("POST");
public static readonly HttpMethod Put = new HttpMethod("PUT");
public static readonly HttpMethod Patch = new HttpMethod("PATCH");
public static readonly HttpMethod Delete = new HttpMethod("DELETE");
private string _name;
public HttpMethod(string name)
{
// validation of name
_name = name.ToUpper();
}
public static implicit operator string(HttpMethod method)
{
return method._name;
}
public static implicit operator HttpMethod(string method)
{
return new HttpMethod(method);
}
public static bool IsValidHttpMethod(string method)
{
// ...
}
public override bool Equals(object obj)
{
// ...
}
public override int GetHashCode()
{
return _name.GetHashCode();
}
public override string ToString()
{
return _name;
}
}
Run Code Online (Sandbox Code Playgroud)
以下代码触发了此问题:
public class HttpRoute
{
public string Prefix { get; }
public HttpMethod[] Methods { get; }
public HttpRoute(string pattern, params HttpMethod[] methods)
{
if (pattern == null) throw new ArgumentNullException(nameof(pattern));
Prefix = pattern;
Methods = methods ?? new HttpMethod[0];
}
public bool CanAccept(HttpListenerRequest request)
{
return Methods.Contains(request.HttpMethod) && request.Url.AbsolutePath.StartsWith(Prefix);
}
}
Run Code Online (Sandbox Code Playgroud)
通过将HttpMethod结构更改为密封类来创建编译器错误.报告错误return Methods.Contains(request.HttpMethod),注意:request.HttpMethod在这种情况下是a string.产生以下内容:
Error CS1929 'HttpMethod[]' does not contain a definition for 'Contains' and the best extension method overload 'Queryable.Contains<string>(IQueryable<string>, string)' requires a receiver of type 'IQueryable<string>'
Run Code Online (Sandbox Code Playgroud)
我的问题是为什么?我可以重新设计代码以使其工作,但我想知道为什么从struct更改为sealed类会产生这种奇怪的错误.
编辑:添加一组简化的示例代码(可在此处获取:https://dotnetfiddle.net/IZ9OXg).注意到,评论了第二类的隐性操作字符串允许代码进行编译:
public static void Main()
{
HttpMethod1[] Methods1 = new HttpMethod1[10];
HttpMethod2[] Methods2 = new HttpMethod2[10];
var res1 = Methods1.Contains("blah"); //works
var res2 = Methods2.Contains("blah"); //doesn't work
}
public struct HttpMethod1
{
public static implicit operator HttpMethod1(string method)
{
return new HttpMethod1();
}
public static implicit operator string (HttpMethod1 method)
{
return "";
}
}
public class HttpMethod2
{
public static implicit operator HttpMethod2(string method)
{
return new HttpMethod2();
}
//Comment out this method and it works fine
public static implicit operator string (HttpMethod2 method)
{
return "";
}
}
Run Code Online (Sandbox Code Playgroud)
Eri*_*ert 10
我知道的事情:
HttpMethod1[],IEnumerable<string>因为协方差仅适用于引用类型.HttpMethod2[],IEnumerable<string>因为协方差仅适用于引用转换,这是用户定义的转换.我怀疑但需要确认的事情:
更新:
IEnumerable<char>,偶尔会混淆类型推断.)这是一个显示问题的程序片段; 更新您的转化以转换为C而不是字符串:
public interface IFoo<out T> {}
public class C {}
public class Program
{
public static bool Contains<T>(IFoo<T> items, T item)
{
System.Console.WriteLine(typeof(T));
return true;
}
public static void Main()
{
IFoo<HttpMethod1> m1 = null;
IFoo<HttpMethod2> m2 = null;
var res1 = Contains(m1, new C()); //works
var res2 = Contains(m2, new C()); //doesn't work
}
}
Run Code Online (Sandbox Code Playgroud)
这看起来像是类型推断中的一个可能的错误,如果是,那就是我的错; 如果是这样的话会有很多道歉.可悲的是,我今天没有时间进一步研究它.你可能想在github上打开一个问题,让一个人仍然以此为生.我会着迷于了解结果是什么,以及它是否是设计或推理算法实现中的错误.