11

この小さなサンプル クラスを取り上げます (私の実際のコードではありませんが、問題が明らかになります)。

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

DoubleまたはTDateTime関数を次のように使用するまでは、問題なくコンパイルされます。

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 に答える