5

C#でクラス(クラスAと呼びます)を定義し、そのための算術演算子の一部をオーバーロードしました。加算演算子に焦点を当てましょう(他の演算子も同様に動作すると思いますが)。クラスAを設定して、スカラー(つまり、単一のDouble値)を追加したり、スカラーに追加したり、Aの2つのインスタンスを一緒に追加したりできるようにしました。

したがって、C#では、「+」演算子が3つの異なる署名でオーバーロードされています。明示的に署名は次のとおりです。

  • A+ダブル
  • ダブル+A
  • A + A

PowerShellでクラスを操作すると、3つのオーバーロードのうちの1つしか認識されません。したがって、PowerShellではA + Doubleを実行できますが、他の2つの式はエラーを引き起こします。

AのインスタンスでGet-Memberコマンドレットを使用すると、3つのオーバーロードすべてを「認識」しているように見えますが、リストの最初のオーバーロードのみを尊重しています。

これは仕様によるものだと思います。私はPowerShellが大好きですが、C#とは大きく異なり、オーバーロードされた演算子に対して1つの署名しか許可せず(これまでに学んだことに基づいて)、式の左側のメンバーが追加のタイプを決定することを期待しています。実行。誰でも確認できますか?

私の回避策は、クラスのC#でいくつかのより詳細な静的メソッド(「AddScalar」や「AddA」メソッドなど)をコーディングすることです。PowerShellでは、「+」演算子を使用するのではなく、これらの名前付きメソッドを呼び出します。これは正常に機能するはずですが、PowerShellに、追加される内容に基づいて「+」の適切な定義を使用させると便利です。

署名が異なるオーバーロードされたクラス演算子を使用して成功した人はいますか?それとも、この種の動作はPowerShellの基本的な設計目標を破るでしょうか?

更新: Dugasはそれを釘付けにしました。しかし、私は途中で何か他のことを学び、それをここに投稿したいと思いました。

クラスAIの追加を定義したとき、クラスAの2つのインスタンスを追加すると、クラスAの新しいインスタンスが生成されるか、NULLが生成されるように定義されました。(これは、加算を実際に閉じる必要があるため、私の側では貧弱な設計でした。言い換えると、理想的には、加算は常に別の加算演算子によって実行できるものを生成する必要があります。)C#では、これ以上加算することはなかったため、これは問題ではありませんでした。一度に2つ以上のオブジェクトを処理し、結果を調べたときにNULLをチェックしました。

操作の結果がNULLの場合、PowerShellはNULLを返す代わりに、op_Addition演算子に対して「オブジェクト参照が設定されていません...」エラーをスローします。PowerShellが間違ったオーバーロードされた演算子を使用しようとしたときに、型変換の実行に問題があったときにNULL参照が作成されていると想定して、このエラーを誤って解釈しました。

オブジェクトのA+Aケースを再実行しました。合計すると、クラスAの別のオブジェクトインスタンスが返され、すべてが正常に機能しました。

要約すると、a1、a2、およびa3がすべてクラスAのインスタンスであり、dがDoubleであり、a1 + a2=NULLおよびa1+a3 = aX(aXはクラスAの新しいインスタンス)である場合、...

  • d + a1#PowerShellはクラスAを取得するDoubleの演算子を認識せず、クラスAをDoubleに変換できないため、失敗します。
  • a1 + d#期待どおりに機能する
  • a1 + a2#失敗します。結果がNULLであるため、「オブジェクト参照が設定されていません...」エラーがスローされます。
  • a1 + a3#期待どおりに動作します。

私を正しい方向に導いてくれてありがとう!

4

1 に答える 1

2

私は好奇心からこれをテストしました。私は次のようなクラスを作成しました:

namespace ClassLibrary1
{
 public class Class1
 {
  public static string operator +(Class1 class1, double d)
  {
   return "a";
  }

  public static string operator +(double d, Class1 class1)
  {
   return "b";
  }

  public static string operator +(Class1 class1, Class1 class12)
  {
   return "c";
  }
 }
}

Class1を最初のパラメーターとして持つ両方のオーバーロードを呼び出すことはできましたが、doubleを最初のパラメーターとして持つオーバーロードを呼び出すことはできませんでした。なぜA+Aのオーバーロードを呼び出せなかったのかわかりません。おそらく、正しい演算子オーバーロードをディスパッチする以外の別の理由でしたか?

$a = New-Object ClassLibrary1.Class1
($a + 0) -eq 'a' # Was True
($a + $a) -eq 'c' # Was True

オーバーロードの呼び出し:

([double]0 + $a) -eq 'b'

エラーが発生しました:

タイプ「ClassLibrary1.Class1」の「ClassLibrary1.Class1」値をタイプ「System.Double」に変換できません。

したがって、最初の引数が演算子がオーバーロードされている型である限り、さまざまな演算子オーバーロードを呼び出すことができると思いますか?

于 2012-10-18T21:46:50.537 に答える