”関数”を受けるパラメータ型(ByRef)について

解決


モモ  2007-02-03 19:22:13  No: 135129

VB.NET2005です。
ユーザ共通関数へのパラメータとして”関数”を渡したいのですが、
受け取り側の型をどうすればよいのか分かりません…
フォームForm1にSyori1という関数
-----------
Private Sub Syori1()

End Sub
-----------
があります。
ユーザ共通関数
-----------
Public Sub ComSyori1(ByRef ParSyori As ????)
    Call ParSyori()
    ※条件により実行する関数が違う
End Sub
-----------
を定義し、
これをフォームForm1から
-----------
Call ComSyori1(Me.Syori1)
-----------
といった具合に呼び出したいのですが、
受け側の????部分が分かりません。
そもそもそういった事が出来るのかどうか分かりませんが、
教えて下さい。
私なりに調べましたところ
Action(Of T)(obj As T)が該当する?ように思いますが、
使用方法が分かりません。
全く違っていたらすみません…
何卒よろしくお願い致します。


Blue  2007-02-03 19:54:36  No: 135130

デリゲードで渡せばよいのでは?(ByRef関係ないと思うけど)


我龍院  2007-02-05 18:46:45  No: 135131

>>Action(Of T)(obj As T)が該当する?ように思いますが、
これは、MSDNには
>>このデリゲートは、Array.ForEach メソッドおよび List.ForEach メソッドによって、
>>配列またはリストの各要素に対して操作を実行する場合に使用されます
となっているので、関数にも依りますが、違うのでは。
よくあるやつは、
Imports System
Imports System.Collections.Generic
Public Class Form1
    Private Class ShoriAll
        Shared Function Shori1(ByVal x As Integer, ByVal y As Integer) As Integer
            Return x + y
        End Function
        Shared Function Shori2(ByVal x As Integer, ByVal y As Integer) As Integer
            Return x * y
        End Function
        Shared Function Shori3(ByVal x As Integer, ByVal y As Integer) As Integer
            Return CInt(x ^ y)
        End Function
    End Class
    Private Delegate Function DelegateShori(ByVal x As Integer, ByVal y As Integer) As Integer
    Private Function Shori(ByVal x As Integer, ByVal y As Integer, ByVal Mydelegate As DelegateShori) As Integer
        Return Mydelegate(x, y)
    End Function
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Console.WriteLine(Shori(2, 3, AddressOf ShoriAll.Shori1))
        Console.WriteLine(Shori(2, 3, AddressOf ShoriAll.Shori2))
        Console.WriteLine(Shori(2, 3, AddressOf ShoriAll.Shori3))
    End Sub
End Class
こんなのかな。


モモ  2007-02-08 00:12:30  No: 135132

お返事ありがとうございます。
”デリゲート”恥ずかしながら初めて知りました。
見よう見まねで動的にメソッドを実行する事は出来たのですが、
次のようにイベントハンドラを追加する共通処理で
メソッドを登録するにはどうすればよいか教えて下さい。
現在、フォーム毎に初期処理にて
----------------------------------------------
フォーム1
Private Sub EventHandler_Add()
  Dim WkControl As Control
  For Each WkControl In Me.Controls
    AddHandler WkControl.Enter, AddressOf Me.All_Enter
  End For
End Sub

Private Sub All_Enter(ByVal sender As Object, ByVal e As System.EventArgs)
  〜略〜
End Sub
----------------------------------------------
といった具合に(動的に)Enterイベントハンドラを追加しています。
ところがフォーム毎に毎回同じコードを記述し実行していますので
これを共通モジュールに移設し、必要な情報(フォーム、
関数ポインタ?)をパラメータとして渡すことで
共通化を図りたいと思っています。
----------------------------------------------
共通モジュール
Public Sub EventHandler_Add(ByRef ParForm As Form)
  Dim WkControl As Control
  For Each WkControl In ParForm.Controls
    AddHandler WkControl.Enter, AddressOf ********
  End For
End Sub
----------------------------------------------
********の部分は各フォームの”All_Enter”という関数を
登録したいのですが、どうすればよいですか?
何卒よろしくお願い致します。


魔界の仮面弁士  2007-02-08 02:33:23  No: 135133

> Public Sub EventHandler_Add(ByRef ParForm As Form)
ここで、ByRef にする必要は無いかと。
(むしろ ByVal にすべきかと思いますが)

>  For Each WkControl In Me.Controls
これですと、フォーム直下のコントロールは対象になりますが、
Panel や GroupBox などの下にあるコントロールが対象外と
なるような気がしますが、それで良いのでしょうか?

> End For
文法エラーかと。

> ********の部分は各フォームの”All_Enter”という関数を
> 登録したいのですが、どうすればよいですか?

=== (案1) 共通モジュールに、デリゲートを渡す ===
  Public Sub EventHandler_Add(ByVal target As Form, ByVal enterMethod As EventHandler)
    For Each childControl As Control In target.Controls
      AddHandler childControl.Enter, EnterMethod
    Next
  End Sub
----
  Public Class Form1
    Private Sub All_Enter(ByVal sender As Object, ByVal e As EventArgs)
      '処理
    End Sub
  End Class

=== (案2) All_Enter を、インターフェイスとして公開しておく ===
  Interface IEnter
    Sub All_Enter(ByVal sender As Object, ByVal e As EventArgs)
  End Interface
----
  Public Sub EventHandler_Add(ByVal target As IEnter)
    If TypeOf target Is Form Then
      For Each childControl As Control In DirectCast(target, Control).Controls
        AddHandler childControl.Enter, AddressOf target.All_Enter
      Next
    End If
  End Sub
----
  Public Class Form1
    Implements IEnter
    Private Sub All_Enter(ByVal sender As Object, ByVal e As EventArgs) Implements IEnter.All_Enter
      '処理
    End Sub
  End Class

=== (案3) Private な All_Enter メソッドに無理矢理アクセス(非推奨) ===
  Public Sub EventHandler_Add(ByVal target As Form)
    Dim method As System.Reflection.MethodInfo = target.GetType().GetMethod( _
      "All_Enter", _
      System.Reflection.BindingFlags.Public _
        Or System.Reflection.BindingFlags.NonPublic _
        Or System.Reflection.BindingFlags.Instance _
        Or System.Reflection.BindingFlags.IgnoreCase _
        Or System.Reflection.BindingFlags.DeclaredOnly, _
      System.Type.DefaultBinder, _
      New Type() {GetType(Object), GetType(EventArgs)}, _
      Nothing)
    If method IsNot Nothing Then
      Dim enterDelegate As EventHandler = System.Delegate.CreateDelegate(GetType(EventHandler), target, "All_Enter", True)
      For Each childControl As Control In DirectCast(target, Control).Controls
        AddHandler childControl.Enter, enterDelegate
      Next
    End If
  End Sub


モモ  2007-02-08 05:50:52  No: 135134

お返事ありがとうございました。
また開発マシンとネット環境マシンが異なりコピペ出来ず手打ちしたため、
文法エラーで申し訳ございませんでした。
PanelとGroupBoxに対するコードも実際は入っていたのですが、
(コピペも出来ませんでしたし、)本筋に関係なかったため
勝手に割愛しておりました。
ご心配をお掛けしてすみませんでした。
なお本題の件は案1でばっちりです。
魔界の仮面弁士様にはいつも助けられてばかりで
心から尊敬致しております。
本当にありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加