C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[3]: C#の匿名メソッドをVBに置き換えるには・・・


(過去ログ 38 を表示中)

[トピック内 12 記事 (1 - 12 表示)]  << 0 >>

■19845 / inTopicNo.1)  C#の匿名メソッドをVBに置き換えるには・・・
  
□投稿者/ jiioi (1回)-(2008/05/30(Fri) 21:40:16)

分類:[.NET 全般] 

jiioiと申します。
今、VB2005を勉強しているところです。
環境 Visual Studio 2005 Professional Edition
WindowsXP Professional です。
下記のC#のコードをVBに置き換えているのですが、どうしても匿名メソッドのところが分かりません。
お分かりになられる方、どうか御教授お願いいたします。



C#のコード


public abstract
class  Arraylib {
	public delegate bool  DSearchArray<T>( T[]  array, int  index );
	private delegate void  DSplit_AddToList( int  iSubStart, int  iSubEnd );
	public static
	T[][]  Split<T>( T[]  array, DSearchArray<T>  delimit ) {
		// 部分配列のリスト
		System.Collections.Generic.List<T[]>  list = new System.Collections.Generic.List<T[]>();
		bool  hasData = false;
		int   iStart  = -1;
		
		// 部分配列を抜き出してリストに追加するデリゲート
		DSplit_AddToList  addToList = delegate( int  iSubStart, int  iSubEnd ) {
								int  subcnt = iSubEnd - iSubStart;
								T[]  arraySub = new T[subcnt];
								Array.Copy( array, iSubStart, arraySub, 0, subcnt );
								list.Add( arraySub );
							};
		
		// ソース配列を走査する
		for( int  i = 0; i < array.Length; i++ ) {
			if( delimit(array, i) ) {
				// 区切り位置を見つけた
				if( hasData ) {
					// 部分配列を抜き出してリストに追加する
					addToList( iStart, i );
					hasData = false;
				}
			} else if( ! hasData ) {
				iStart  = i;
				hasData = true;
			}
		}
		if( hasData ) {
			// 部分配列を抜き出してリストに追加する
			addToList( iStart, array.Length );
			hasData = false;
		}

		return  list.ToArray();
	}
	
}

VBに置き換えているコード

   Public MustInherit Class Arraylib
        Public Delegate Function DSearchArray(Of T)(ByVal array As T(), ByVal index As Integer) As Boolean
        Private Delegate Sub DSplit_AddToList(ByVal iSubStart As Integer, ByVal iSubEnd As Integer)

         Public Shared Function Split(Of T)(ByVal array As T(), ByVal delimit As DSearchArray(Of T)) As T()()
            ' 部分配列のリスト
            Dim list As New System.Collections.Generic.List(Of T())()
            Dim hasData As Boolean = False
            Dim iStart As Integer = -1

            ' 部分配列を抜き出してリストに追加するデリゲート
            Dim addToList As DSplit_AddToList
            addToList = New DSplit_AddToList(AddressOf AddList())

            ' ソース配列を走査する
            For i As Integer = 0 To array.Length - 1
                If delimit(array, i) Then
                    ' 区切り位置を見つけた
                    If hasData Then
                        ' 部分配列を抜き出してリストに追加する
                        addToList.Invoke(iStart, i)
                        hasData = False
                    End If
                ElseIf Not hasData Then
                    iStart = i
                    hasData = True
                End If
            Next
            If hasData Then
                ' 部分配列を抜き出してリストに追加する
                addToList.Invoke(iStart, array.Length)
                hasData = False
            End If

            Return list.ToArray()

        Private Sub AddList(ByVal iSubStart As Integer, ByVal iSubEnd As Integer)
            Dim subcnt As Integer = iSubEnd - iSubStart
            Dim arraySub As T() = New T(subcnt - 1) {}
            array.Copy(array, iSubStart, arraySub, 0, subcnt)
            list.Add(arraySub)
        End Sub
     End Function

    End Class

引用返信 編集キー/
■19847 / inTopicNo.2)  Re[1]: C#の匿名メソッドをVBに置き換えるには・・・
□投稿者/ Azulean (129回)-(2008/05/30(Fri) 22:15:06)
具体的にどこが分からないのでしょうか。

ちなみに、このC#の匿名メソッドは、匿名(デリゲート)である必要を感じません。
要するにこういう関数があれば良いはずなので。

private static void AddToList<T>(T[] array, List<T[]> list, int iSubEnd, int iSubStart)
{
    int subcnt = iSubEnd - iSubStart;
    T[] arraySub = new T[subcnt];
    Array.Copy(array, iSubStart, arraySub, 0, subcnt);
    list.Add(arraySub);
}

これをヒントにVB.NETのコードを書き起こせば良いのではないですか。

引用返信 編集キー/
■19848 / inTopicNo.3)  Re[1]: C#の匿名メソッドをVBに置き換えるには・・・
□投稿者/ 片桐 (99回)-(2008/05/30(Fri) 22:16:35)
なにがどうエラーなのかわからないのですが……

すくなくとも、VBは1sub、1Functionで完結しないといけないのでは?
入れ子はできないと思いますです……
引用返信 編集キー/
■19851 / inTopicNo.4)  Re[1]: C#の匿名メソッドをVBに置き換えるには・・・
□投稿者/ 魔界の仮面弁士 (751回)-(2008/05/30(Fri) 22:39:21)
No19845 (jiioi さん) に返信
> C#のコード
このコードは何故、わざわざ匿名メソッドを用いて実装されているのでしょう?
 DSplit_AddToList  addToList = delegate( int  iSubStart, int  iSubEnd ) { … }
で用意された匿名メソッドを、後から
 addToList( iStart, i );
で呼び出しているようですが、それならば最初から
 static void AddToList<T>(int iSubStart, int iSubEnd, T[] array, List<T[]> list) { … }
のようなメソッドを作っておいて、ループ中で
 AddToList<T>( iStart, i, array, list );
としておいても良いような。


> VBに置き換えているコード
DSplit_AddToList デリゲートを使わない実装に直した方が良いような気がしますが、
あえて元コードの仕様をそのまま残すのであれば、こうかな。


Public MustInherit Class Arraylib
    Private Class anonymous(Of T)
        Private tArray() As T
        Private tList As List(Of T())
        Public Sub New(ByVal array() As T, ByVal list As List(Of T()))
            tArray = array
            tList = list
        End Sub
        Public Shared Narrowing Operator CType(ByVal o As anonymous(Of T)) As DSplit_AddToList
            Return AddressOf o.AddToListCallback
        End Operator
        Private Sub AddToListCallback(ByVal iSubStart%, ByVal iSubEnd%)
            Dim subcnt As Integer = iSubEnd - iSubStart
            Dim arraySub(subcnt - 1) As T
            Array.Copy(tArray, iSubStart, arraySub, 0, subcnt)
            tList.Add(arraySub)
        End Sub
    End Class

    Public Shared Function Split(Of T)(ByVal array As T(), ByVal delimit As DSearchArray(Of T)) As T()()
        ' 部分配列のリスト
        Dim list As New System.Collections.Generic.List(Of T())()
        Dim hasData As Boolean = False
        Dim iStart As Integer = -1

        ' 部分配列を抜き出してリストに追加するデリゲート
        Dim addToList As DSplit_AddToList = New anonymous(Of T)(array, list)
          :
        …略…
          :
    End Function
       :
     …略…
       :
End Class

引用返信 編集キー/
■19852 / inTopicNo.5)  Re[2]: C#の匿名メソッドをVBに置き換えるには・・・
□投稿者/ jiioi (3回)-(2008/05/30(Fri) 23:31:46)
みなさん、回答ありがとうございます。
普段はVBで開発しているのですが、C#のコードサンプルをVBで置き換えるときに匿名メソッドが出てきてどうしても変換方法がわかりませんでした。
ジェネリックというのも今回知ったところです。

>  static void AddToList<T>(int iSubStart, int iSubEnd, T[] array, List<T[]> list) { … }
> のようなメソッドを作っておいて、ループ中で
>  AddToList<T>( iStart, i, array, list );
> としておいても良いような。

みなさん、同じことをおっしゃっているとおもいますが、実際VBで組むにはどのようにしたらよいでしょう。
よろしくおながいします。

引用返信 編集キー/
■19855 / inTopicNo.6)  Re[3]: C#の匿名メソッドをVBに置き換えるには・・・
□投稿者/ Azulean (131回)-(2008/05/31(Sat) 00:00:33)
> みなさん、同じことをおっしゃっているとおもいますが、実際VBで組むにはどのようにしたらよいでしょう。
その「同じこと」の中にVBのコードも入っていませんか?

また、**今回の元のコードでは正しく変換されません**が、ある程度のC#のコードはVB.NETのコードに自動で変換できます。
例えば、私の示したC#のメソッドは変換できますね。
http://labs.developerfusion.co.uk/convert/csharp-to-vb.aspx

あとはコード片をうまく組み合わせるだけでなんとかなるはずですよ。
引用返信 編集キー/
■19856 / inTopicNo.7)  Re[3]: C#の匿名メソッドをVBに置き換えるには・・・
□投稿者/ 魔界の仮面弁士 (752回)-(2008/05/31(Sat) 00:02:06)
No19852 (jiioi さん) に返信
> 匿名メソッドが出てきてどうしても変換方法がわかりませんでした。
VB には匿名メソッドが無いですからね。

で、C# の場合、匿名メソッドが IL へとコンパイル際には、一時的なクラスが
作成され、そのメソッドをデリゲートとしているようです。それを模倣したのが、先のコード。


>> static void AddToList<T>(int iSubStart, int iSubEnd, T[] array, List<T[]> list) { … }
>>のようなメソッドを作っておいて、ループ中で
>> AddToList<T>( iStart, i, array, list );
>>としておいても良いような。
> みなさん、同じことをおっしゃっているとおもいますが、実際VBで組むにはどのようにしたらよいでしょう。

まずは C# で組むと、こう。

public abstract class  Arraylib
{
  // 元々は、匿名メソッドにしていた部分
  private static void AddToList<T>(int iSubStart, int iSubEnd, T[] array, List<T[]> list)
  {
    int  subcnt = iSubEnd - iSubStart;
    T[]  arraySub = new T[subcnt];
    Array.Copy( array, iSubStart, arraySub, 0, subcnt );
    list.Add( arraySub );
  }

  public static T[][]  Split<T>( T[]  array, DSearchArray<T>  delimit )
  {
    // 部分配列のリスト
    System.Collections.Generic.List<T[]>  list = new System.Collections.Generic.List<T[]>();
    bool  hasData = false;
    int   iStart  = -1;

    // ソース配列を走査する
    for( int  i = 0; i < array.Length; i++ )
    {
        …略…
        // 部分配列を抜き出してリストに追加する
        /*
           addToList( iStart, i ); // 匿名メソッドの呼び出し
        */ 
        AddToList<T>( iStart, i, array, list );
        …略…
     }
        …略…
     return  list.ToArray();
  }
}


それを VB 化すると、こうかな。

Private Shared Sub AddToList(Of T)(iSubStart%, iSubEnd%, array() As T, list As List(Of T()) )
   Dim subcnt As Integer = iSubEnd - iSubStart
   Dim arraySub(subcnt - 1) As T
   Array.Copy(tArray, iSubStart, arraySub, 0, subcnt)
   tList.Add(arraySub)
End Sub

Public Shared Function Split(Of T)(ByVal array As T(), ByVal delimit As DSearchArray(Of T)) As T()()
   Dim list As New System.Collections.Generic.List(Of T())()
   Dim hasData As Boolean = False
   Dim iStart As Integer = -1

   For i As Integer = 0 To array.Length - 1
      …略…
      ' 部分配列を抜き出してリストに追加する
      '' addToList.Invoke(iStart, i)
      AddToList(Of T)( iStart, i, array, list )
      …略…
   Next
   …略…
   Return list.ToArray()
End Function

引用返信 編集キー/
■19878 / inTopicNo.8)  Re[4]: C#の匿名メソッドをVBに置き換えるには・・・
□投稿者/ jiioi (4回)-(2008/06/01(Sun) 01:32:34)
ありがとうございます。
大変勉強になっています。
もう一点わからないところがあるのですが、

> Private Shared Sub AddToList(Of T)(iSubStart%, iSubEnd%, array() As T, list As List(Of T()) )
> Dim subcnt As Integer = iSubEnd - iSubStart
> Dim arraySub(subcnt - 1) As T
> Array.Copy(tArray, iSubStart, arraySub, 0, subcnt)
> tList.Add(arraySub)
> End Sub

このメソッドに引数を渡して処理を行っているとおもうのですが、
Byval値渡しで処理をして返してもよいものなのでしょうか?
BYREF参照渡しならよいのか?
そのあたりが理解出来ていません。
よろしくお願いいたします。

引用返信 編集キー/
■19880 / inTopicNo.9)  Re[5]: C#の匿名メソッドをVBに置き換えるには・・・
□投稿者/ 魔界の仮面弁士 (753回)-(2008/06/01(Sun) 02:19:23)
No19878 (jiioi さん) に返信
> このメソッドに
ありゃ。No19851 のコードをコピーしたせいで、微妙に引数名と変数名が
食い違っていますね…。適宜修正しておいてください。m(_ _;m

> Byval値渡しで処理をして返してもよいものなのでしょうか?
> BYREF参照渡しならよいのか?
それぞれの使い分け方に付いては、こちらが参考になるかと。
http://msdn.microsoft.com/ja-jp/library/ddck1z30.aspx
引用返信 編集キー/
■19902 / inTopicNo.10)  Re[6]: C#の匿名メソッドをVBに置き換えるには・・・
□投稿者/ jiioi (5回)-(2008/06/01(Sun) 09:01:36)
参考のところをよみました。
値渡し→プロシージャからはその値を変更できないようにする
参照渡し→値を変更できる
ということですよね。
では
Private Shared Sub AddToList(Of T)(iSubStart%, iSubEnd%, array() As T, list As List(Of T()) )
このメソッドは引数が値渡しになってて、処理しても呼び出し元が変更されてないのではないのでしょうか?

引用返信 編集キー/
■19904 / inTopicNo.11)  Re[7]: C#の匿名メソッドをVBに置き換えるには・・・
□投稿者/ Azulean (133回)-(2008/06/01(Sun) 12:57:23)
2008/06/01(Sun) 13:05:50 編集(投稿者)
> Private Shared Sub AddToList(Of T)(iSubStart%, iSubEnd%, array() As T, list As List(Of T()) )
> このメソッドは引数が値渡しになってて、処理しても呼び出し元が変更されてないのではないのでしょうか?
その辺は参照型と値型の違いによってややこしくなっています。

List(Of T)や配列はクラスで参照型です。ByValで渡そうと、List(Of T)や配列の中身を変更できます。

では、ByValとByRefは何が変わるか?
呼び出し元のその変数がどのList(Of T)や配列を指し示すのかを変更できるかどうかです。
ByRefの場合に新しい配列をその変数に入れると、呼び出し元でもその配列が使われます。

http://msdn.microsoft.com/ja-jp/library/eek064h4.aspx

参考
具体的な説明はしませんが、出力結果からなぜそうなるかを考えてみて下さい。

Sub Test1(ByVal array() As Integer)
    array(1) = 123
    ReDim array(100)
    array(2) = 234
End Sub

Sub Test2(ByRef array() As Integer)
    array(1) = 345
    ReDim array(100)
    array(2) = 456
End Sub

Sub Main()
    Dim b(10) As Integer
    b(1) = 25
    b(2) = 30
    Console.WriteLine("First")
    Console.WriteLine("b.Length:" & b.Length.ToString())
    Console.WriteLine("b(1):" & b(1).ToString())
    Console.WriteLine("b(2):" & b(2).ToString())

    ' ByVal
    Test1(b)
    Console.WriteLine("After Test1")
    Console.WriteLine("b.Length:" & b.Length.ToString())
    Console.WriteLine("b(1):" & b(1).ToString())
    Console.WriteLine("b(2):" & b(2).ToString())

    ' ByRef
    Test2(b)
    Console.WriteLine("After Test2")
    Console.WriteLine("b.Length:" & b.Length.ToString())
    Console.WriteLine("b(1):" & b(1).ToString())
    Console.WriteLine("b(2):" & b(2).ToString())

End Sub

引用返信 編集キー/
■19909 / inTopicNo.12)  Re[8]: C#の匿名メソッドをVBに置き換えるには・・・
□投稿者/ jiioi (6回)-(2008/06/02(Mon) 01:20:53)
大変興味深い例題を出していただきありがとうございました。
予想と結果が惜しくも違っており、勉強になります。
どうもありがとうございました。


予想
First
b.Length:11
b(1):25
b(2):30
AfterTest1
b.Length:11
b(1):123
b(2):234←結果はb(2):30
AfterTest2
b.Length:101
b(1):0
b(2):456
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -