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);
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が派生するsum = first + second ステートメントの場合、binder.OperationExpressionType.Addを返します。

arg
Object

バイナリ演算の右オペランド。 たとえば、DynamicObject クラスからfirstsecondが派生するsum = first + second ステートメントの場合、argsecondと等しくなります。

result
Object

バイナリ演算の結果。

返品

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

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

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

この例では、加算演算と減算演算のみがサポートされています。 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 メソッドがオーバーライドされると、 sum = first + secondmultiply = first*secondなどのステートメントに対して自動的に呼び出されます。ここで、 firstDynamicObject クラスから派生します。

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

動的オブジェクトが 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# で動的オブジェクトの OrElse (a || b) および AndAlso (a && b) 操作を実装するには、 TryUnaryOperation メソッドと TryBinaryOperation メソッドの両方を実装する必要があります。

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

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

適用対象