C# 不明确的函数重载 - rectangle 与 rectanglef
C# Ambiguous function overload - rectangle vs. rectanglef
我有一行代码
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)'
显然这是正确的,因为有过载。如何指定我要使用矩形?
此处的错误消息具有误导性。这两个重载之间的调用实际上是不明确的:
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);
因为:
- 存在从
Rectangle
到 RectangleF
(第一个参数)的隐式转换
- 存在从
int
到 float
(最后一个参数)的隐式转换
- 存在从
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
参数的方法,因为身份转换优于隐式转换。
然而,这不是编译器所做的。编译器只寻找一个最好的成员。如果找不到它,它会报告错误。错误消息基于整个适用的成员列表,并且可以包含该列表中的任何方法签名。
我有一行代码
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)'
显然这是正确的,因为有过载。如何指定我要使用矩形?
此处的错误消息具有误导性。这两个重载之间的调用实际上是不明确的:
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);
因为:
- 存在从
Rectangle
到RectangleF
(第一个参数)的隐式转换 - 存在从
int
到float
(最后一个参数)的隐式转换 - 存在从
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
参数的方法,因为身份转换优于隐式转换。
然而,这不是编译器所做的。编译器只寻找一个最好的成员。如果找不到它,它会报告错误。错误消息基于整个适用的成员列表,并且可以包含该列表中的任何方法签名。