11

以这个小示例类为例(不是我的真实代码,但它暴露了问题):

Convert = class(TObject)
  public
    class function ToString(value: Double): String; overload;
    class function ToString(value: TDateTime): String; overload;
  end;

在您尝试使用DoubleTDateTime函数之前,它编译得很好:

var
  d: Double;
begin
  d := 99.99;
  ShowMessage(Convert.ToString(d));

您将收到此编译错误:对“ToString”的模糊重载调用。问题归结为一个TDateTime事实Double

我的问题:您如何处理此类问题?

编辑 - 我不是在为给出的例子寻找解决方案

到目前为止,我找到了 3 个解决方案:

  • 重命名 2 个函数之一
  • 将“虚拟”参数添加到 2 个函数之一
  • 将参数更改为 Var 类型,这样做的缺点是我不能再用常量调用此函数

还有其他解决方案吗?

4

3 回答 3

14

重载方法可能非常有效。但是,一旦出现模棱两可的迹象,它们就会成为一种负担。XE3 中引入的新 TStream 重载就是一个很好的例子。不难陷入编译器选择了您没想到的重载的陷阱。至少在您的代码中,编译器停止了。从这个意义上说,你是幸运的。

因此,在您的情况下,我的建议是放弃重载。在方法名称中表达不同的输入类型。是的,它有点冗长,但你不会犯任何错误,而且你的代码会编译!

于 2013-01-05T09:04:44.013 回答
5

您发布的示例在 XE 中编译和执行良好。

在评论中,您改为给出此示例:

ShowMessage( Convert.ToString( 99.99 ));  // <- gives compiler error 2251

在这种特殊情况下,解决方案是明确定义类型(我认为):

ShowMessage( Convert.ToString( Double(99.99) )); // <- E2089, Invalid Typecast

查看文档:

此错误消息针对规则不允许的类型转换发出。允许以下类型的演员表:

  • 序数或指针类型到另一个序数或指针类型
  • 字符、字符串、字符数组或 pchar 到字符串
  • 变体的序数、实数、字符串或变体
  • 序数、实数、字符串或变体的变体
  • 对任何大小相同的类型的变量引用。

因此,要明确告诉编译器选择Double重载函数:

ShowMessage( Convert.ToString( Double(Variant(99.99)))); // Ok

可能有点绕。但对于其他重载函数,它更简单:

ShowMessage( Convert.ToString( EncodeDate(2013,1,5));

更新


要使其成为适用于所有类的通用解决方案,请考虑添加类函数来解决您的模棱两可的类型。

Convert = Class(TObject)
  ...
  class function AsDouble( value: Double) : Double; inline; static;
  class function AsTDateTime( value: TDateTime) : TDateTime; inline; static;
end;

class function Convert.AsDouble(value: Double): Double;
begin
  Result := Value;
end;
class function Convert.AsDateTime(value: TDateTime): TDateTime;
begin
  Result := Value;
end;

现在你可以用常量调用你的重载类函数:

ShowMessage( Convert.ToString( Convert.AsDouble(99.99)));   
于 2013-01-05T09:42:46.007 回答
1

把它全部折叠怎么样?:

class function Convert.ToString(value: Variant): String;
begin
   Result := VarToStr(Value);
end;
于 2013-01-05T11:05:08.197 回答