ソース掲示板




すべてから検索

キーワード   条件 表示 現行ログ 過去ログ トピックス 名前 本文
オブジェクトに対するオペレータの定義 ( No.4 )
日時: 2008/05/05 23:03
名前: lightbox




C++ での実装とは少し違うようですが、以下のような演算子を自分の作成したオブジェクト
に対して特別な実装を施す事ができます


OperatorOperand CountDescription
+UnaryPositive
-UnaryNegative
IsFalseUnaryIs False test
IsTrueUnaryIs True test
NotUnaryNegation
+BinaryAddition
-BinarySubtraction
*BinaryMultiplication
/BinaryFloating-point division
\BinaryInteger division
&BinaryConcatenation
^BinaryExponentiation
>>BinaryShift right
<<BinaryShift left
=BinaryEquality; assignment
cannot be overloaded
<>BinaryNot equal
>BinaryGreater than
<BinaryLess than
>=BinaryGreater than or equal to
<=BinaryLess than or equal to
AndBinaryBitwise and
LikeBinaryString pattern matching
ModBinaryModulo division
OrBinaryBitwise or
XorBinaryBitwise xor
CTypeUnaryType conversion
実装時に知っておく必要のある仕様としては、

1) クラスメソッドとして定義する必要がえる
2) ペアとなる演算子は同時に定義する必要がある
3) 演算子によっては、引数の型が決められているものがある
4) 第1引数に、自分自身の型を定義する事によって呼ばれた時にインスタンスが引き渡される
テスト用のレジストリを扱うクラス
' **************************************************
' クラス定義
' **************************************************
Imports Microsoft.Win32

Public Class RegCur

	Public regkey As RegistryKey = Nothing
	Public svpath As String = Nothing


	' **************************************************
	' コンストラタ
	' **************************************************
	Public Sub New(ByVal path As String)

		regkey = Registry.CurrentUser.OpenSubKey(path, True)
		svpath = path

	End Sub

	' **************************************************
	' 比較演算子を代入して再OPENに利用
	' **************************************************
	Public Shared Operator =(ByVal target As RegCur, ByVal path As String) As Boolean

		Dim ret As Boolean = False

		If Not target.regkey Is Nothing Then
			target.regkey.Close()
		End If

		target.regkey = Registry.CurrentUser.OpenSubKey(path, True)
		If Not target.regkey Is Nothing Then
			ret = True
		End If

		Return ret

	End Operator

	' **************************************************
	' 比較演算子を代入して再OPENに利用
	' **************************************************
	Public Shared Operator <>(ByVal target As RegCur, ByVal path As String) As Boolean

		Dim ret As Boolean = False

		If Not target.regkey Is Nothing Then
			target.regkey.Close()
		End If

		target.regkey = Registry.CurrentUser.OpenSubKey(path, True)
		If target.regkey Is Nothing Then
			ret = True
		End If

		Return ret

	End Operator

	' **************************************************
	' C++ で言うところの キャスト演算子( String 用 )
	' Widening は 損失の無い変換
	' **************************************************
	Public Shared Widening Operator CType(ByVal value As RegCur) As String

		If value Is Nothing Then
			Return ""
		Else
			Return value.svpath
		End If

	End Operator

	' **************************************************
	' 演算子では無いが、String 用の Ctype と同じにする
	' デフォルトでは、クラス名が返る(含む名前空間)
	' **************************************************
	Public Overrides Function ToString() As String

		Return Me.svpath

	End Function

End Class
レジストリのキーを再度別のキーで開けなおす際に、 = の右辺がキーで、成功した時に true が返ります。
<> を使うと、成功した時に false が返ります。

( ※ = と <> は、本来比較演算子です )
実行サンプル
Imports Microsoft.Win32

Public Class Form1

	Private Sub Form1_Load(ByVal sender As System.Object, _
	 ByVal e As System.EventArgs) Handles MyBase.Load

		Dim reg As RegCur = New RegCur("Environment")

		MessageBox.Show(reg.regkey.GetValue("PATH").ToString())

		If reg = "Software\Microsoft\Ftp" Then
			MessageBox.Show(CStr(reg.regkey.GetValue("Use PASV")))
		Else
			MessageBox.Show("キーが存在しません")
		End If

		If reg = "Software\Microsoft\Internet Explorer" Then
			MessageBox.Show(CType(reg.regkey.GetValue("Download Directory"), String))
		Else
			MessageBox.Show("キーが存在しません")
		End If

		If reg <> "Environment" Then
			MessageBox.Show("キーが存在しません")
		Else
			MessageBox.Show(Convert.ToString(reg.regkey.GetValue("TMP")))
		End If

	End Sub
End Class
VB.NET では、通常自作オブジェクトを = や <> 演算子で比較しないので問題無いですが、
このまま C# に変換した場合は、C# では null との比較が存在するので考慮が必要です

VB での オブジォクトがインスタンスかどうかの判断
if Object is Nothing then
	' もともと is Nothing を使うので、= オペレターは使われない
end if

C# での オブジォクトがインスタンスかどうかの判断
if ( null == Object ) {
	// null を左辺に持って来る事によって、定義された == オペレータは発動しない
end if
C#
public class RegCur
{

	public RegistryKey regkey = null;
	public string svpath = null;

	public RegCur(string path)
	{

		regkey = Registry.CurrentUser.OpenSubKey(path, true);
		svpath = path;

	}

	public static bool operator ==(RegCur target, string path)
	{
		bool ret = false;

		if ((target.regkey != null))
		{
			target.regkey.Close();
		}

		target.regkey = Registry.CurrentUser.OpenSubKey(path, true);
		if ((target.regkey != null))
		{
			ret = true;
		}

		return ret;

	}

	public static bool operator !=(RegCur target, string path)
	{

		bool ret = false;

		if ((target.regkey != null))
		{
			target.regkey.Close();
		}

		target.regkey = Registry.CurrentUser.OpenSubKey(path, true);
		if (target.regkey == null)
		{
			ret = true;
		}

		return ret;

	}

}