【问题标题】:C# Ambiguous function overload - rectangle vs. rectanglefC# 模糊函数重载 - 矩形与矩形f
【发布时间】:2015-10-28 11:04:50
【问题描述】:

我有一行代码

System.Drawing.Drawing2D.LinearGradientBrush gradient = new System.Drawing.Drawing2D.LinearGradientBrush(new System.Drawing.Rectangle(5, 5, 100, 100), Color.Red, Color.Green, 0);

这会引发错误

The call is ambiguous between the following methods or properties: 'LinearGradientBrush.LinearGradientBrush(RectangleF, Color, Color, LinearGradientMode)' and 'LinearGradientBrush.LinearGradientBrush(Rectangle, Color, Color, LinearGradientMode)'

显然这是正确的,因为有过载。如何指定我要使用 Rectangle?

【问题讨论】:

    标签: c# ambiguous


    【解决方案1】:

    这里的错误信息非常具有误导性。这两个重载之间的调用实际上是模棱两可的:

    public LinearGradientBrush(Rectangle rect, Color color1, Color color2, float angle);
    public LinearGradientBrush(Rectangle rect, Color color1, Color color2, LinearGradientMode linearGradientMode);
    

    问题是您试图将最后一个参数作为int 而不是LinearGradientMode 传递。如果您传递 LinearGradientMode 枚举值,它将编译:

    gradient = new LinearGradientBrush(
                     new Rectangle(5, 5, 100, 100), 
                     Color.Red, 
                     Color.Green, 
                     LinearGradientMode.Horizontal);
    

    编辑

    一些解释为什么在这种情况下错误消息如此具有误导性:

    C# 中重载解析的过程在 C# 语言规范的第 7.5.3 节中进行了描述。

    第一步是创建一组适用的函数成员。基本上(忽略params和可选参数),这些都是与调用中指定的参数数量相同的方法,并且从每个参数到相应参数的类型都有隐式转换。

    有 4 个适用的构造函数 LinearGradientBrush 用于传递的参数:

    public LinearGradientBrush(RectangleF rect, Color color1, Color color2, LinearGradientMode linearGradientMode);
    public LinearGradientBrush(RectangleF rect, Color color1, Color color2, float angle);
    public LinearGradientBrush(Rectangle rect, Color color1, Color color2, float angle);
    public LinearGradientBrush(Rectangle rect, Color color1, Color color2, LinearGradientMode linearGradientMode);
    

    因为:

    • 存在从 RectangleRectangleF 的隐式转换(第一个参数)
    • 存在从 intfloat 的隐式转换(最后一个参数)
    • 存在从 0 到任何 enum 类型(最后一个参数)的隐式转换

    从这个列表中,编译器尝试找到最适合调用的成员。如果失败,则报告错误。错误消息仅包含适用成员列表中 2 个方法的签名。

    如果我们想使用第 7.5.3.2 节中描述的规则对这些成员进行排序,我们会得到

    1. public LinearGradientBrush(Rectangle, Color, Color, float);
    1. public LinearGradientBrush(Rectangle, Color, Color, LinearGradientMode);
    3. public LinearGradientBrush(RectangleF, Color, Color, float);
    3. public LinearGradientBrush(RectangleF, Color, Color, LinearGradientMode); 
    

    采用Rectangle 参数的方法优于采用RectangleF 参数的方法,因为标识转换优于隐式转换。

    但是,编译器不是这样做的。编译器只寻找一个最好的成员。如果找不到,则会报告错误。错误消息基于整个适用的成员列表,并且可以包含该列表中的任何方法签名。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-14
      • 2014-10-03
      • 1970-01-01
      相关资源
      最近更新 更多