ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c# – VS 2015方法重载解析行为

2019-07-02 17:54:33  阅读:278  来源: 互联网

标签:c overloading visual-studio-2015 net-4-5 generics


我很难理解为什么在这个简单的例子中没有选择正确的过载.看看7.5.3.2更好的函数成员下的C# 5 spec,它似乎应该能够选择非泛型的重载,但是对象参数似乎在某种程度上影响了我不理解的决定.我遇到的问题是我不能在不将参数转换为object的情况下调用非泛型版本的Foo(对象).从错误来看,它似乎不受支持,我希望有人可以了解原因.

public class A
{
    public string Type { get { return "non-generic"; } }
}

public class A<T>
{
    public string Type { get { return "generic"; } }
}

class Program
{
    // (In reality only one of the variants below can be uncommented.)
    static void Main(string[] args)
    {
        // This works fine and calls the generic overload as expected
        A<string> x = Foo<string>("foobar");

        // This results in a compile time error
        // CS0029: Cannot implicitly convert type 'A<string>' to 'A'
        A x = Foo("foobar");

        // This works, but ends up calling the generic overload
        var x = Foo("foobar");

        // This works fine and calls the non-generic overload as expected
        object a = "foobar";
        var x = Foo(a);

        // This works fine and calls the non-generic overload as expected
        A x = Foo((object)"foobar");

        // By using dynamic we're able to get rid of the compile-time error, but get a
        // runtime exception.
        // RuntimeBinderException: Cannot implicitly convert type 'A<string>' to 'A'
        A x = Foo((dynamic)"foobar");

        Console.WriteLine(x.Type);
        Console.ReadLine();
    }

    private static A Foo(object x)
    {
        return new A();
    }

    private static A<T> Foo<T>(T x)
    {
        return new A<T>();
    }
}

解决方法:

A x = Foo("foobar");

C#选择泛型方法,因为它比非泛型方法更具体,不需要转换.实际上,C#编译器创建了Foo方法的副本,并用具体类型字符串替换泛型类型参数T.重载决策在编译时执行.在运行时,将调用带有字符串参数的方法.在运行时不会创建通用开销.

请注意,分辨率仅考虑分配右侧的表达式.更具体地说,C#查看方法签名,即方法参数.方法的返回类型不属于其签名.

通用方法返回A< T>,但由于A< T>,因此返回A< T>.不是来自A,A< T>类型的结果.方法Foo< T>()的方法不能分配给类型A的x.对于具有动态的示例也是如此:没有来自A< T>的有效转换.到A.由于重载解析是在编译时完成的,因此动态无法解决您的问题. Dynamics正在运行时执行“工作”(即绑定).

同样,这不是您期望从确定使用哪个重载的方法的结果,而是传递给此方法的(静态)参数.

另一个有助于澄清事实的例子:

var x = Foo(5);
var y = Foo("hello");

在编译时,C#创建Foo方法的两个副本!一个用int和一个用string代替泛型类型参数T.在运行时没有发生转换;甚至不是拳击(不像Java那样将int包装成一个对象).

标签:c,overloading,visual-studio-2015,net-4-5,generics
来源: https://codeday.me/bug/20190702/1358589.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有