VisualBasic.PowerPacks.ShapeContainer について

タグの編集
投稿者 VB+VC# Beginner  (社会人) 投稿日時 2020/9/3 20:43:41
Microsoft.VisualBasic.PowerPacks.ShapeContainer についてお尋ねします。
Windows Form に Lineshape を描画するために、VisualBasic.PowerPacks をインストールしました。
Lineshape を複数個描画すると、VB では、Designer.vb の中に、
        Me.ShapeContainer1.Shapes.AddRange(New Microsoft.VisualBasic.PowerPacks.Shape() {
          Me.LineShape_00, Me.LineShape_01, ... })
の記述が見つかったので、Lineshape のプロパティーを
        For i=0 to 59
            Me.ShapeContainer1.Shapes(i).X2 = ??
        Next
のように、For ~Next で設定することができました。
その後、VisualBasic.PowerPacks を VC# でも利用できることを知り、同じことができるか試してみました。
Designer.cs の中に、
            this.shapeContainer1.Shapes.AddRange(new Microsoft.VisualBasic.PowerPacks.Shape[] {
            this.lineShape00, this.lineShape01, ... });
の記述が見つかったので、
            Me.ShapeContainer1.Shapes[0] 
と入力すると、
「CS0020 角かっこ [] 付きインデックスを 'type' 型の式に適用することはできません」
のエラーが出ます。
ShapeContainer1.Shapes がたくさんあると、「ShapeContainer1.Shapes(i).」の書き方ができると
非常に便利です。
VC# で同様のことができるか教えて下さい。

投稿者 魔界の仮面弁士  (社会人) 投稿日時 2020/9/3 22:46:23
>  Me.ShapeContainer1.Shapes[0] 
> と入力すると、
> 「CS0020 角かっこ [] 付きインデックスを 'type' 型の式に適用することはできません」

えぇと…??? 質問内容に混乱が見られるような。
◾ CS0020 は確かに C# コンパイラのエラーコードですが、その意味は
 「定数 0 による除算」だったはずです。 CS0021 の間違いではありませんか?

◾ C# に Me というキーワードはありません。this の間違いではありませんか?

◽ Visual Basicの命名ルールが何故か引き継がれているようですね。
 Visual Basicで作られたデザイン情報を、たとえばクリップボードを使うなどして
 C# 側に移植したということでしょうか?  Name プロパティの初期設定は
 PascalCase 表記な ShapeContainer1 が Visual Basic デザイナによるもので
 camelCase 表記な shapeContainer1 が C# デザイナのものとなるはずなので…。


> VC# で同様のことができるか教えて下さい。

Microsoft.VisualBasic.PowerPacks.ShapeCollection クラスはインデクサを有していません。
『インデクサ』ではなく、『引数付きプロパティ』として実装されています。
https://docs.microsoft.com/en-us/previous-versions/bb917992

Visual Basic 側の文法で言えば、
Default Public Property Item(index As IntegerAs Object
は持ち合わせていない、ということです。ただし
Public Property Item(index As IntegerAs Object Implements IList.Item
であれば実装されています。


見ての通り、IList が実装されていますので、引数付きプロパティをサポートしていない C# であっても、
  dynamic shape = ((System.Collections.IList)this.shapeContainer1.Shapes)[0];
のように、IList を通じてアクセスすることが可能です。

あるいは、動的言語サポートを通じて、
  dynamic shapes = this.shapeContainer1.Shapes;
  dynamic shape = shapes[0];
  shapes[0] = shape;   // 使わないとは思うけれど、代入操作も可能
のように書くこともできます。



そのほか、引数付きプロパティを持つクラスが C# 側に引き渡された場合、
getter / setter のメソッドを通じてアクセスすることができます。たとえば、

'Dim shape As Object = Me.ShapeContainer1.Shapes(0)
Dim shape As Object = Me.ShapeContainer1.Shapes.Item(0)
Me.ShapeContainer1.Shapes.Item(0) = shape

に相当するコードを C# では

dynamic shape = this.shapeContainer1.Shapes.get_Item(0);
this.shapeContainer1.Shapes.set_Item(0, shape);

のように書けます。
https://ufcpp.net/blog/2016/12/tipsimplicitmembers/


ちなみに Visual Basic 側でも、サポートされていない演算子のオーバーロードを呼び出すために、
このような代替名でのアクセスが必要になるケースがあるのですが…それはまた別のお話。
投稿者 VB+VC# Beginner  (社会人) 投稿日時 2020/9/4 00:36:22
魔界の仮面弁士様
早速ご回答ありがとうございました。

おっしゃる通り、
「this.shapeContainer1.Shapes[0].」
「CS0021」
の間違いでした。

ご回答の方法は明日以降に試してみます。
とりあえず「方法はある」ことがわかり、安心しました。