拡張メソッドについて

タグの編集
投稿者 Jaip  (社会人) 投稿日時 2012/2/10 02:21:39
お世話になります。いつも参考させていただいております。

拡張メソッドについて確認したいことがあります。

1.拡張メソッドのエディタ表示の際にオブジェクトを引数にして呼び出すときは非表示にして、
拡張メソッドとして呼び出すときは表示するということは可能でしょうか、
EditorBrowsableAttributeのEditorBrowsableState.Neverだとどちらの場合も非表示にされてしまいます。
出来なくて困るわけではなく、単なる好奇心レベルの質問です。

Module ExtendsModule


<Extension()>
Public Sub exMethod(ByVal X As Class1)
'略 
End Sub


End Module

Dim x As New Class1
'エディタ非表示 
exMethod(x)
'エディタ非表示 
ExtendsModule.exMethod(x)
'エディタ表示 
x.exMethod()



2.VBではインクリメント/デクリメントがないので下記のような拡張メソッドを作成してみて動作は確認したのですが、
拡張メソッドにByRefを使用している例がみないので、使ってはいけない規約とかあるのでしょうか?

Module ExtendsModule

<Extension()>
Public Function PreIncrement(ByRef a As IntegerAs Integer
a += 1
Return a
End Function

<Extension()>
Public Function AftIncrement(ByRef a As IntegerAs Integer
Dim b As Integer = a
a += 1
Return b
End Function

End Module

(1)
Dim i As Integer = 1
Dim j As Integer

j = i.PreIncrement 'i = 2, j = 2 
(2)
Dim i As Integer = 1
Dim j As Integer
j = i.AftIncrement 'i = 2, j = 1 



以上よろしくお願いいたします。
投稿者 YuO  (社会人) 投稿日時 2012/2/10 11:23:22
2. に関しては互換性の問題かと。

C#では ref/out (VB でいう ByRef または <Out>ByRef) と this (VB でいう <Extension>) を同時に使うことができません。
たとえVBで作ったとしても,呼び出し時に out/ref を前置しないといけないため,実質的に拡張メソッドとして呼び出すことができなくなります。
static class Program
{
  static void Increment (this ref int @this) // エラー CS1101: パラメーター修飾子 'ref' は 'this' と共に使用することはできません。 
  {
    ++@this;
  }

  static void Main ()
  {
  }
}


基本的に,VB/C#の片方でしか使えない要素をパブリックインターフェースの一部として使うことは推奨されません。
同様に推奨されない要素としては,デフォルトでない名前付きプロパティがあります。
投稿者 るきお  (社会人) 投稿日時 2012/2/10 12:52:21
VB自体に関していえば、

>1.拡張メソッドのエディタ表示の際にオブジェクトを引数にして呼び出すときは非表示にして、
>拡張メソッドとして呼び出すときは表示するということは可能でしょうか、
多分、不可能です。

>2.VBではインクリメント/デクリメントがないので下記のような拡張メソッドを作成してみて動作は確認したのですが、
>拡張メソッドにByRefを使用している例がみないので、使ってはいけない規約とかあるのでしょうか?
ありません。

VB10の言語仕様書には以下の一節がありますから、状況に応じてByRefの使用を肯定していると受け取れます。
以下抜粋
言語上は、拡張メソッドの最初の引数に対する制限はありませんが、拡張メソッドを使用して値型を拡張しないことをお勧めします。値型を拡張する場合は、副作用が元の値に作用するように最初のパラメーターを ByRef として渡すことをお勧めします。
投稿者 jaip  (社会人) 投稿日時 2012/2/11 01:24:02
Yuoさん、るきおさん

お世話になります。

回答ありがとうございます。

>>1.拡張メソッドのエディタ表示の際にオブジェクトを引数にして呼び出すときは非表示にして、
>>拡張メソッドとして呼び出すときは表示するということは可能でしょうか、
>多分、不可能です。

了解です。何となく気になっただけで問題ないです。

ありません。

>VB10の言語仕様書には以下の一節がありますから、状況に応じてByRefの使用を肯定していると受>け取れます。

勉強になります。使いどころを考えながら使用していきたいと思います。
仕様を見ていて思ったのですが。 のユーザ定義型や配列がByRefしか、指定できないのも同じ理由だろうなと少しすっきりしました(笑)


との互換性については盲点でした。拡張メソッド使えばVBでもインクリメントできるのでは? と考えたところから味待っていたので、C#側で使った場合というのが視野から外れていました。
おかげでだいぶすっきりしました。

本当にありがとうございます。