草庐IT

c# - 将结构更改为密封类时隐式转换失败

coder 2024-05-25 原文

有问题的结构/类:

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;
    }
}

下面的代码触发了这个问题:

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);
    }
}

编译器错误是通过将 HttpMethod 结构更改为密封类而产生的。 return Methods.Contains(request.HttpMethod)报错,注意:request.HttpMethod在本例中是一个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>'

我的问题是为什么?我可以重新设计代码以使其工作,但我想知道为什么从结构更改为密封类会产生这个奇怪的错误。

编辑:添加一组简化的示例代码(可在此处获取: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 "";
    }

}

最佳答案

我知道的事情:

  • 显然问题出在类型推断上。
  • 在第一种情况下,T 被推断为 HttpMethod1。
  • 在 struct 的情况下,没有从 HttpMethod1[] 的转换至 IEnumerable<string>因为协方差仅适用于引用类型。
  • 在类别案例中,没有从 HttpMethod2[] 的转换至 IEnumerable<string>因为协方差仅适用于引用转换,这是用户定义的转换。

我怀疑但需要确认的事情:

  • 关于我的最后两点之间的细微差别的一些事情混淆了类型推断算法。

更新:

  • 它与协变数组转换无关。即使没有数组转换,问题也会重现。
  • 确实但是与协变接口(interface)转换有关。
  • 它与字符串无关。 (字符串通常有点奇怪,因为它们有一个很难记住的 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
    }
    }

这看起来像是类型推断中可能存在的错误,如果是,那是我的错;如果是这样的话,我深表歉意。遗憾的是,我今天没有时间进一步研究它。您可能想在 github 上打开一个问题,让仍然这样做的人来研究它。我很想知道结果是什么,以及它是否是推理算法的设计或实现中的错误。

关于c# - 将结构更改为密封类时隐式转换失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43011140/

有关c# - 将结构更改为密封类时隐式转换失败的更多相关文章

  1. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  2. ruby-on-rails - Ruby on Rails 迁移,将表更改为 MyISAM - 2

    如何正确创建Rails迁移,以便将表更改为MySQL中的MyISAM?目前是InnoDB。运行原始执行语句会更改表,但它不会更新db/schema.rb,因此当在测试环境中重新创建表时,它会返回到InnoDB并且我的全文搜索失败。我如何着手更改/添加迁移,以便将现有表修改为MyISAM并更新schema.rb,以便我的数据库和相应的测试数据库得到相应更新? 最佳答案 我没有找到执行此操作的好方法。您可以像有人建议的那样更改您的schema.rb,然后运行:rakedb:schema:load,但是,这将覆盖您的数据。我的做法是(假设

  3. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  4. ruby - 将数组的内容转换为 int - 2

    我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]

  5. ruby - 将散列转换为嵌套散列 - 2

    这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[

  6. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  7. ruby - Capistrano 3 在任务中更改 ssh_options - 2

    我尝试使用不同的ssh_options在同一阶段运行capistranov.3任务。我的production.rb说:set:stage,:productionset:user,'deploy'set:ssh_options,{user:'deploy'}通过此配置,capistrano与用户deploy连接,这对于其余的任务是正确的。但是我需要将它连接到服务器中配置良好的an_other_user以完成一项特定任务。然后我的食谱说:...taskswithoriginaluser...task:my_task_with_an_other_userdoset:user,'an_othe

  8. ruby - 即使失败也继续进行多主机测试 - 2

    我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r

  9. ruby-on-rails - Ruby url 到 html 链接转换 - 2

    我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.

  10. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

随机推荐