DynamicObject.TryBinaryOperation メソッド

定義

二項演算の実装を提供します。 DynamicObject クラスの派生クラスでこのメソッドをオーバーライドして、加算や乗算などの演算の動的な動作を指定できます。

public:
 virtual bool TryBinaryOperation(System::Dynamic::BinaryOperationBinder ^ binder, System::Object ^ arg, [Runtime::InteropServices::Out] System::Object ^ % result);
public virtual bool TryBinaryOperation (System.Dynamic.BinaryOperationBinder binder, object arg, out object result);
public virtual bool TryBinaryOperation (System.Dynamic.BinaryOperationBinder binder, object arg, out object? result);
abstract member TryBinaryOperation : System.Dynamic.BinaryOperationBinder * obj * obj -> bool
override this.TryBinaryOperation : System.Dynamic.BinaryOperationBinder * obj * obj -> bool
Public Overridable Function TryBinaryOperation (binder As BinaryOperationBinder, arg As Object, ByRef result As Object) As Boolean

パラメーター

binder
BinaryOperationBinder

二項演算に関する情報を提供します。 プロパティは binder.Operation オブジェクトを ExpressionType 返します。 たとえば、 クラスから DynamicObject 派生した ステートメントfirstsecondの 場合、 binder.Operation は を返しますExpressionType.Addsum = first + second

arg
Object

二項演算の右オペランド。 たとえば、 ステートメントの sum = first + second 場合、 firstsecond は クラスから DynamicObject 派生し、 arg は と second等しくなります。

result
Object

二項演算の結果。

戻り値

操作が正常に終了した場合は true。それ以外の場合は false。 このメソッドが false を返す場合、言語のランタイム バインダーによって動作が決まります (ほとんどの場合、言語固有の実行時例外がスローされます)。

数値のテキスト表現と数値表現を格納するデータ構造が必要であり、そのようなデータの加算や減算などの基本的な数学演算を定義する必要があるとします。

次のコード例では、 DynamicNumber クラスから派生した クラスを DynamicObject 示します。 DynamicNumber は、 メソッドを TryBinaryOperation オーバーライドして数学演算を有効にします。 また、 メソッドと TryGetMember メソッドをTrySetMemberオーバーライドして、 要素へのアクセスを有効にします。

この例では、加算演算と減算演算のみがサポートされています。 のような resultNumber = firstNumber*secondNumberステートメントを記述しようとすると、実行時例外がスローされます。

// Add using System.Linq.Expressions;
// to the beginning of the file.

// The class derived from DynamicObject.
public class DynamicNumber : DynamicObject
{
    // The inner dictionary to store field names and values.
    Dictionary<string, object> dictionary
        = new Dictionary<string, object>();

    // Get the property value.
    public override bool TryGetMember(
        GetMemberBinder binder, out object result)
    {
        return dictionary.TryGetValue(binder.Name, out result);
    }

    // Set the property value.
    public override bool TrySetMember(
        SetMemberBinder binder, object value)
    {
        dictionary[binder.Name] = value;
        return true;
    }

    // Perform the binary operation.
    public override bool TryBinaryOperation(
        BinaryOperationBinder binder, object arg, out object result)
    {
        // The Textual property contains the textual representaion
        // of two numbers, in addition to the name
        // of the binary operation.
        string resultTextual =
            dictionary["Textual"].ToString() + " "
            + binder.Operation + " " +
            ((DynamicNumber)arg).dictionary["Textual"].ToString();

        int resultNumeric;

        // Checking what type of operation is being performed.
        switch (binder.Operation)
        {
            // Proccessing mathematical addition (a + b).
            case ExpressionType.Add:
                resultNumeric =
                    (int)dictionary["Numeric"] +
                    (int)((DynamicNumber)arg).dictionary["Numeric"];
                break;

            // Processing mathematical substraction (a - b).
            case ExpressionType.Subtract:
                resultNumeric =
                    (int)dictionary["Numeric"] -
                    (int)((DynamicNumber)arg).dictionary["Numeric"];
                break;

            // In case of any other binary operation,
            // print out the type of operation and return false,
            // which means that the language should determine
            // what to do.
            // (Usually the language just throws an exception.)
            default:
                Console.WriteLine(
                    binder.Operation +
                    ": This binary operation is not implemented");
                result = null;
                return false;
        }

        dynamic finalResult = new DynamicNumber();
        finalResult.Textual = resultTextual;
        finalResult.Numeric = resultNumeric;
        result = finalResult;
        return true;
    }
}

class Program
{
    static void Test(string[] args)
    {
        // Creating the first dynamic number.
        dynamic firstNumber = new DynamicNumber();

        // Creating properties and setting their values
        // for the first dynamic number.
        // The TrySetMember method is called.
        firstNumber.Textual = "One";
        firstNumber.Numeric = 1;

        // Printing out properties. The TryGetMember method is called.
        Console.WriteLine(
            firstNumber.Textual + " " + firstNumber.Numeric);

        // Creating the second dynamic number.
        dynamic secondNumber = new DynamicNumber();
        secondNumber.Textual = "Two";
        secondNumber.Numeric = 2;
        Console.WriteLine(
            secondNumber.Textual + " " + secondNumber.Numeric);

        dynamic resultNumber = new DynamicNumber();

        // Adding two numbers. The TryBinaryOperation is called.
        resultNumber = firstNumber + secondNumber;

        Console.WriteLine(
            resultNumber.Textual + " " + resultNumber.Numeric);

        // Subtracting two numbers. TryBinaryOperation is called.
        resultNumber = firstNumber - secondNumber;

        Console.WriteLine(
            resultNumber.Textual + " " + resultNumber.Numeric);

        // The following statement produces a run-time exception
        // because the multiplication operation is not implemented.
        // resultNumber = firstNumber * secondNumber;
    }
}

// This code example produces the following output:

// One 1
// Two 2
// One Add Two 3
// One Subtract Two -1
' Add Imports System.Linq.Expressions
' to the beginning of the file.
' The class derived from DynamicObject.
Public Class DynamicNumber
    Inherits DynamicObject

    ' The inner dictionary to store field names and values.
    Dim dictionary As New Dictionary(Of String, Object)

    ' Get the property value.
    Public Overrides Function TryGetMember(
        ByVal binder As System.Dynamic.GetMemberBinder,
        ByRef result As Object) As Boolean

        Return dictionary.TryGetValue(binder.Name, result)

    End Function

    ' Set the property value.
    Public Overrides Function TrySetMember(
        ByVal binder As System.Dynamic.SetMemberBinder,
        ByVal value As Object) As Boolean

        dictionary(binder.Name) = value
        Return True

    End Function

    ' Perform the binary operation. 
    Public Overrides Function TryBinaryOperation(
        ByVal binder As System.Dynamic.BinaryOperationBinder,
        ByVal arg As Object, ByRef result As Object) As Boolean

        ' The Textual property contains the textual representaion 
        ' of two numbers, in addition to the name of the binary operation.
        Dim resultTextual As String =
            dictionary("Textual") & " " &
            binder.Operation.ToString() & " " &
        CType(arg, DynamicNumber).dictionary("Textual")

        Dim resultNumeric As Integer

        ' Checking what type of operation is being performed.
        Select Case binder.Operation
            ' Proccessing mathematical addition (a + b).
            Case ExpressionType.Add
                resultNumeric =
                CInt(dictionary("Numeric")) +
                CInt((CType(arg, DynamicNumber)).dictionary("Numeric"))

                ' Processing mathematical substraction (a - b).
            Case ExpressionType.Subtract
                resultNumeric =
                CInt(dictionary("Numeric")) -
                CInt((CType(arg, DynamicNumber)).dictionary("Numeric"))

            Case Else
                ' In case of any other binary operation,
                ' print out the type of operation and return false,
                ' which means that the language should determine 
                ' what to do.
                ' (Usually the language just throws an exception.)
                Console.WriteLine(
                    binder.Operation.ToString() &
                    ": This binary operation is not implemented")
                result = Nothing
                Return False
        End Select

        Dim finalResult As Object = New DynamicNumber()
        finalResult.Textual = resultTextual
        finalResult.Numeric = resultNumeric
        result = finalResult
        Return True
    End Function
End Class

Sub Test()
    ' Creating the first dynamic number.
    Dim firstNumber As Object = New DynamicNumber()

    ' Creating properties and setting their values
    ' for the first dynamic number. 
    ' The TrySetMember method is called.
    firstNumber.Textual = "One"
    firstNumber.Numeric = 1

    ' Printing out properties. The TryGetMember method is called.
    Console.WriteLine(
        firstNumber.Textual & " " & firstNumber.Numeric)

    ' Creating the second dynamic number.
    Dim secondNumber As Object = New DynamicNumber()
    secondNumber.Textual = "Two"
    secondNumber.Numeric = 2
    Console.WriteLine(
        secondNumber.Textual & " " & secondNumber.Numeric)

    Dim resultNumber As Object = New DynamicNumber()

    ' Adding two numbers. TryBinaryOperation is called.
    resultNumber = firstNumber + secondNumber
    Console.WriteLine(
        resultNumber.Textual & " " & resultNumber.Numeric)

    ' Subtracting two numbers. TryBinaryOperation is called.
    resultNumber = firstNumber - secondNumber
    Console.WriteLine(
        resultNumber.Textual & " " & resultNumber.Numeric)

    ' The following statement produces a run-time exception
    ' because the multiplication operation is not implemented.
    ' resultNumber = firstNumber * secondNumber
End Sub

' This code example produces the following output:

' One 1
' Two 2
' One Add Two 3
' One Subtract Two -1

注釈

クラスから DynamicObject 派生したクラスは、動的オブジェクトに対してバイナリ操作を実行する方法を指定するために、このメソッドをオーバーライドできます。 メソッドがオーバーライドされない場合、言語の実行時バインダーによって動作が決定されます。 (ほとんどの場合、言語固有の実行時例外がスローされます)。

このメソッドは、加算や乗算などのバイナリ演算がある場合に呼び出されます。 たとえば、 メソッドがTryBinaryOperationオーバーライドされた場合、 や multiply = first*secondなどのsum = first + secondステートメントに対して自動的に呼び出されます。ここでfirstDynamicObject は クラスから派生します。

パラメーターの プロパティを使用して、バイナリ操作の種類に関する Operation 情報を binder 取得できます。

動的オブジェクトが C# と Visual Basic でのみ使用されている場合、 binder.Operation プロパティは 列挙体から次のいずれかの値を ExpressionType 持つことができます。 ただし、IronPython や IronRuby などの他の言語では、他の値を使用できます。

[値] 説明 C# Visual Basic
Add 数値オペランドのオーバーフロー チェックを行わない加算演算。 a + b a + b
AddAssign 数値オペランドのオーバーフロー チェックを行わない加算複合代入操作。 a += b サポートされていません。
And ビットごとの AND 操作。 a & b a And b
AndAssign ビットごとの AND 複合代入操作。 a &= b サポートされていません。
Divide 算術除算演算。 a / b a / b
DivideAssign 算術除算複合代入演算。 a /= b サポートされていません。
ExclusiveOr ビットごとの XOR 操作。 a ^ b a Xor b
ExclusiveOrAssign ビットごとの XOR 複合代入操作。 a ^= b サポートされていません。
GreaterThan "より大きい" 比較。 a > b a > b
GreaterThanOrEqual "以上" の比較。 a >= b サポートされていません。
LeftShift ビットごとの左シフト操作。 a << b a << b
LeftShiftAssign ビットごとの左シフト複合代入操作。 a <<= b サポートされていません。
LessThan "より小さい" 比較。 a < b a < b
LessThanOrEqual "以下" の比較。 a <= b サポートされていません。
Modulo 算術剰余演算。 a % b a Mod b
ModuloAssign 算術剰余複合代入演算。 a %= b サポートされていません。
Multiply 数値オペランドのオーバーフロー チェックを行わない乗算演算。 a * b a * b
MultiplyAssign 数値オペランドのオーバーフロー チェックを行わない乗算複合代入演算。 a *= b サポートされていません。
NotEqual 等しくない比較。 a != b a <> b
Or ビットごとの操作または論理 OR 演算。 a &#124; b a Or b
OrAssign ビットごとのまたは論理複合 OR の割り当て。 a &#124;= b サポートされていません。
Power 数値を累乗する数学的演算。 サポートされていません。 a ^ b
RightShift ビットごとの右シフト操作。 a >> b a >> b
RightShiftAssign ビットごとの右シフト複合代入操作。 a >>= b サポートされていません。
Subtract 数値オペランドのオーバーフロー チェックを行わない減算演算。 a - b a - b
SubtractAssign 数値オペランドのオーバーフロー チェックを行わない減算複合代入演算。 a -= b サポートされていません。

Note

C# で動的オブジェクトに対して (a || b) 操作と AndAlso (a && b) 操作を実装OrElseするには、 メソッドと メソッドの両方をTryBinaryOperationTryUnaryOperation実装できます。

操作は OrElse 、単項 IsTrue 演算とバイナリ Or 演算で構成されます。 操作は Or 、操作の IsTrue 結果が の場合にのみ実行されます false

操作は AndAlso 、単項 IsFalse 演算とバイナリ And 演算で構成されます。 操作は And 、操作の IsFalse 結果が の場合にのみ実行されます false

適用対象