Assigning a Value to Structure's Member Accessed via Collection

このQ&Aのポイント
  • When trying to assign a value to a structure's member that is accessed via a collection, an error message 'Expression is a value and cannot be target of an assignment' is displayed.
  • The issue has been reported to Microsoft and is being investigated.
  • There is currently no known solution or workaround for this issue.
回答を見る
  • ベストアンサー

assigning a value to structure's member accessed via collection

Class SampleA Private SampleAPoints As New System.Collections.Generic.List(Of System.Drawing.Point) Public ReadOnly Property Points As System.Collections.Generic.List(Of System.Drawing.Point) Get Return SampleAPoints End Get End Property End Class Class himajin100000 Shared Sub Main Dim Samp As New SampleA Samp.Points.Add(New System.Drawing.Point(80,80)) Samp.Points(0).X = 40 Samp.Points(0).Y = 40 End Sub End Class 'とかやってたら 'Expression is a value and cannot be target of an assignment 'といわれてしまいました。 '参考 'http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=295107 'どうやって切り抜けますか?

質問者が選んだベストアンサー

  • ベストアンサー
  • dsuekichi
  • ベストアンサー率64% (171/265)
回答No.2

ANo.1です。 > >何がエラーの原因かは理解されていますよね? > 【いいえ】。 #以下は、私の認識ですので、ひょっとしたら間違っているかも・・・ > Samp.Points.Add(New System.Drawing.Point(80,80)) このとき何がおきるかと言うと、 ・「System.Drawing.Point構造体」の「値」を作成 ・「一時変数_1」に 作成した構造体の「値」を設定 ・「一時変数_2」に SampのCollectionの「参照情報」を設定 ・「一時変数_2」にある「参照情報」を元に「Add」を実行し、  「一時変数_1」にある構造体の「値」を追加 で、その後一時変数は消滅する。 Point構造体の「値」はCollectionに格納される。 > Samp.Points(0).X = 40 このときは、 ・「一時変数_1」にSampのCollectionの「参照情報」を設定 ・「一時変数_1」の「参照情報」を元に設定されていた構造体の「値」を参照 ・「 一時変数_2」に構造体の「値」を設定 ・「 一時変数_2」のXに40を設定 で、一時変数は消滅。設定したつもりの「40」も霧と消える。 もし、Pointが構造体ではなく、クラスなら、 > Samp.Points.Add(New System.Drawing.Pointクラス(80,80)) このとき何がおきるかと言うと、 ・「System.Drawing.Pointクラス」の「実体」を作成 ・「一時変数_1」に 作成したクラスの「参照情報」を設定 ・「一時変数_2」に SampのCollectionの「参照情報」を設定 ・「一時変数_2」にある「参照情報」を元に「Add」を実行し、  「一時変数_1」にある、クラスの「参照情報」を追加 で、その後一時変数は消滅する。 Pointクラスの「参照情報」はCollectionに格納され、参照先には、クラスの「実体」がある。 > Samp.Points(0).X = 40 このときは、 ・「一時変数_1」にSampのCollectionの「参照情報」を設定 ・「一時変数_1」の「参照情報」を元に設定されていたクラスの「参照情報」を参照 ・「 一時変数_2」にクラスの「参照情報」を設定 ・「 一時変数_2」の「参照情報」を元に、クラスの「実体」のXに40を設定 で、一時変数は消滅するが「40」は「実体」に設定されているので、残る。 > >私なら、Collectionをあきらめて配列にするかな・・・ > 当初、そう思ってました。 ふむ。 > 新たにクラスを作成し構造体をメンバ変数にしてプロパティでアクセスできるようにし, なるほど・・・こちらのほうが良いかな・・・ でも、構造体自体をメンバにて公開にしたら同じことですよね。 #「参照情報」ではなく、構造体の「値」しか見えない。 「値変更用のメンバ」(たとえば、XとY)をクラスのメンバにしてやれば・・・ で、構造体を直接公開したメンバは「値参照」専用として使う。 #「参照情報」でイメージわかりますか? #参照型の変数に代入される、実体を指し示している値(多分アドレス)のことです。

その他の回答 (1)

  • dsuekichi
  • ベストアンサー率64% (171/265)
回答No.1

> 'Expression is a value and cannot be target of an assignment > 'といわれてしまいました。 何がエラーの原因かは理解されていますよね? > どうやって切り抜けますか? 私なら、Collectionをあきらめて配列にするかな・・・

himajin100000
質問者

お礼

回答ありがとうございます。 >何がエラーの原因かは理解されていますよね? 【いいえ】。 これっぽいな、と思って添付はしてみたものの、 英文読んでもわかりません。(いっぺん死ね>俺) (「計算結果」として扱われている、という意図のことが書いてあるのはわかるし、上記エラーメッセージもそう書いてあるのだが, 自分の力では「(Connectの記述によると)クラスだと何故成功するのか」を説明できない なお、temp variableを設けても結局コレクションの値を変更できないから変数が増えるだけでイヤン。 方針を変えてみて,新たにクラスを作成し構造体をメンバ変数にしてプロパティでアクセスできるようにし,このクラスのコレクション・・・でもやっぱり同じエラーが。) >私なら、Collectionをあきらめて配列にするかな・・・ 当初、そう思ってました。 ところで,個人的なポリシーとしてVB6→VB.NETな人間なのでVB.NETの方が書きやすいため、VB.NETで書いてますが,出来る限りC#等でも同じ書き方でいけるように書いています。 Collectionを配列でやるとなると・・・・ http://oshiete1.goo.ne.jp/qa3277715.html あたりで後々尾を引いて泥沼になりそうだなあ・・・という予感がしています。 http://bbs.wankuma.com/index.cgi?mode=al2&namber=7173 の ■7218を適当に利用して Samp.Points.item(0) = New System.Drawing.Point(40,40) とかやったところうまくいったようです。 #時機を見たり、気が向いたりしたら,締め切ります

関連するQ&A

  • VB6構造体をVB2008クラスで行う場合

    何方かの質問「VB6構造体をVB2008クラスで行う場合」 の回答プログラムにて参考とさせて頂きましたが 申し訳ありません、初心者しにて・・・・・教えてください。 値を「登録、参照部分」のクラス(抜粋) Public Class Program   Public Shared Sub Main()    (省略)   End Sub End Class 上記部分なのですが (1)Sharedを使用する訳はなんでしょうか?(省いても問題ありませんか?) (2)登録、参照部分のクラスPublic Shared Sub Main()を「登録のメソッド」と「参照のメソッド」に   分けたいのですがどうしてもうまくいきません。   何方か御教授願えないでしょうか? よろしくお願いします。 「以下何方かの質問の回答プログラム」 ■クラス+コレクションクラス Public Class Group   Public MainID As Integer   Public SubID As Integer   Public Value1 As Integer   Public Value2 As Integer End Class Public Class GroupCollection : Inherits System.Collections.Generic.Dictionary(Of Integer, Group)   Public Shadows Sub Add(ByVal Item As Group)     MyBase.Add(Item.SubID, Item)   End Sub End Class Public Class Program   Public Shared Sub Main()     Dim DataDict As New GroupCollection     Dim NewGroup As New Group     NewGroup.MainID = 1     NewGroup.SubID = 101     NewGroup.Value1 = 123     NewGroup.Value2 = 234     DataDict.Add(NewGroup)     Console.WriteLine(DataDict.Item(101).Value2) ' 出力 234   End Sub End Class

  • 構造体のジェネリックのインスタンス化について

    先日、C++を始めたばかりの者です。 Visual C++ 2008を使って、Windowsフォームアプリケーションを作っているのですが、以下のように、 List<Point>^ pts = new List<Point>(); とすると、この行で、コンパイルエラー:C3845 "ref クラス または値型の内部で、スタティック データ メンバのみ初期化することができます"と、なってしまいます。 System::Collections::Genericと、System::Drawingはusing済みです。 回答、よろしくお願いします。

  • フォームを画面のど真ん中に表示させたいのですが

    フォームを画面のど真ん中に表示させたいのですが、 http://dobon.net/vb/dotnet/form/startposition.html を見たのですがコードの書き方がよくわかりません。 Public Class Form1 Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load Dim f As New Form1() 'フォームを画面の真ん中に表示する f.StartPosition = FormStartPosition.CenterScreenf.Show() End Sub End Class こうすると、「FormStartPosition.CenterScreenf」の部分に波線がひかれます。 Public Class Form1 Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load Me.StartPosition = FormStartPosition.Manual Me.Location = New Point(0, 0) End Sub End Class これで左は時に表示する事は出来るのですが、真ん中に表示させるにはどうすればいいでしょうか?

  • Visual Basic でスクリーンショット

    学生で、visual basic を勉強しているものです Button1をクリックするとスクリーンショットを1秒ごとに撮り、 "c:\iMonitoring"に保存するというプログラムを書いています (Button2をクリックすると止まる) 写真の名前を撮った時刻にしたいのですがエラーが出てうまくいきません どうしていいか分からばいので教えてください (コードです) ********************************************************************************* Public Class Form1 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Timer1.Enabled = False System.IO.Directory.CreateDirectory("C:\iMonitoring") End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Timer1.Enabled = True End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Timer1.Enabled = False End Sub Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick Dim x As String = Now().ToString() Dim a As String = "C:\iMonitoring\" Dim b As String = ".bmp" Dim y As String = (a & x & b) 'Imports System.Drawing 'Imports System.Windows.Forms 'Bitmapの作成 Dim bmp As New Bitmap(Screen.PrimaryScreen.Bounds.Width, _ Screen.PrimaryScreen.Bounds.Height) 'Graphicsの作成 Dim g As Graphics = Graphics.FromImage(bmp) '画面全体をコピーする g.CopyFromScreen(New Point(0, 0), New Point(0, 0), bmp.Size) '解放 g.Dispose() '保存 bmp.Save(y) End Sub End Class

  • Visual Basicがわかりません。

    Public Class Form1 Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint Dim GraphicsFun As System.Drawing.Graphics GraphicsFun = Me.CreateGraphics Dim PenColor As New System.Drawing.Pen _ (System.Drawing.Color.Black) GraphicsFun.DrawRectangle(PenColor, 30, 30, 450, 300) End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Timer1.Enabled = True End Sub Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick If PictureBox1.Left < 480 - PictureBox1.Width And PictureBox1.Top + 31 Then PictureBox1.Left = PictureBox1.Left + 1 Else If PictureBox1.Top < 330 - PictureBox1.Height Then PictureBox1.Top = PictureBox1.Top + 1 Else If PictureBox1.Left > 30 Then PictureBox1.Left = PictureBox1.Left - 1 Else If PictureBox1.Top > 30 And PictureBox1.Left + 31 Then PictureBox1.Top = PictureBox1.Top - 1 End If End If End If End If End Sub End Class ピクチャーボックスを四角形の中で右周りに枠の中をボタンを押すと回るようにしたいんですけど、2回目の動作と3回目の動作がかぶってしまい、うまくいきません。4回目の解決策を教えてください。また、ボタン2を押すと反対周りにピクチャーボックスが回る、コマンドを 教えてください。

  • VBAでクラス設定

    (標準モジュール) Option Explicit Sub test() Dim Class As Class1 Set Class = New Class1 Class.Obj = 1000 Set Class = Nothing Set Class = New Class1 Range("a1").Value = Class.Obj Set Class = Nothing End Sub (クラスモジュールClass1) Option Explicit Private a As Integer Public Property Get Obj() As Integer Obj = 2000 End Property Public Property Let Obj(ByVal NewNumber As Integer) a = NewNumber End Property 上のマクロではやり取り1変数になってますがこれを配列に変えたいのですがどうすればいいでしょうか?

  • プロパティープロシージャーについて

    簡単な年齢計算プログラムです。 書籍のサンプルなのでうまく動いています。 クラスの変数がPrivate strnameだったりするので そこへアクセスするためにプロパティプロシージャーを使っているというところまでは 判ったような気がしますが、 getとsetの関係がわかりません。 まず、 1.何をGetしているのか 2.なぜGetが先に来るのか、 3.Setの前にGetのReturnで返してますが実態は何を返しているのでしょうか?普通に考えると逆のような気がします。 根本がわかっていないのだと思いますが、どなたかお教え願います。 呼ぶ方 Public Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim person As New Class1() person.Name = TextBox1.Text person.Birthday = DateTimePicker1.Value.Date MessageBox.Show(person.Name & "さんの年齢は" & person.GetAge()) End Sub クラスの方。 Public Class Class1 Private strname As String Private datBirthday As Date Public Property Name() As String Get Return strname End Get Set(ByVal pro_name As String) strname = pro_name End Set End Property Public Property Birthday() As Date Get Return datBirthday End Get Set(ByVal pro_birthday As Date) datBirthday = pro_birthday End Set End Property Public Function GetAge() As Integer Return Int(DateTime.Today.Subtract(Birthday).Days / 365.25) End Function End Class

  • グラフィックスの読み取りについて。

    Option Strict On 'VisualBasic2008(無料版) Imports System.Drawing.Drawing2D Public Class Form1 Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint Dim myFont As New Font("Arial", 20, FontStyle.Bold) e.Graphics.DrawString("7", myFont, Brushes.Red, 0, 0) End Sub End Class 例えば、こんな感じのプログラムがあるとします。 PictureBox1のサイズは25*25です。 PictureBox1内のグラフィックスの読み取りがしたいのです。 質問__1 ドット単位で625のデータをARGBで読み取り配列に格納したいです。 質問__2 グラフィックスが表示されてる場合は1を代入、表示されてない場合は0を代入、配列に入れたいです。イチゼロデータを作りたいです。 よろしくお願いします。

  • 自動生成コードを変更したい(VB.NET) 続

    前回の質問内容に説明が足りなかったので、詳細を書きます。 下記のようなTextBoxを継承した、ユーザコントロールを作成します。Textプロパティの初期値として、AAAを設定します。 Public Class UserControl1 Inherits System.Windows.Forms.TextBox #Region " Windows フォーム デザイナで生成されたコード " (中略) <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent() ' 'UserControl1 ' Me.Text = "AAA" End Sub #End Region End Class 作成したユーザコントロールをフォームに追加します。すると、下記のようにTextが自動設定され、TextがUserControl11になってしまします。 このフォームに追加した時に自動で設定されるコードの部分を変更するにはどうしたらよいのでしょうか。 Public Class Form2 Inherits System.Windows.Forms.Form #Region " Windows フォーム デザイナで生成されたコード " (中略) Friend WithEvents UserControl11 As ImputmanTest.UserControl1 <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent() Me.UserControl11 = New ImputmanTest.UserControl1 Me.SuspendLayout() ' 'UserControl11 ' Me.UserControl11.Location = New System.Drawing.Point(112, 200) Me.UserControl11.Name = "UserControl11" Me.UserControl11.TabIndex = 5 Me.UserControl11.Text = "UserControl11" (中略) End Sub #End Region End Class

  • メソッドの作成方法

    メソッドの作成方法に関して不明な点がありますので教えてください。 次の例はExcel VBAで作成したものです。 ---- Class Point ---- Public x As Integer, y As Integer ---- Class Line ---- Public FromPoint As Point, ToPoint As Point Sub Clear() Set FromPoint = New Point ToPoint.x = 0 ToPoint.y = 0 End Sub ---- テスト用プログラム ---- Sub test() Dim a As New Point, b As New Point, c As New Line a.x = 1 a.y = 2 b.x = 3 b.y = 4 Set c.FromPoint = a Set c.ToPoint = b c.Clear End Sub -------- 以上のプログラムにおいて test を実行すると c.Clear を実行したとき a の内容は変化しませんが b の内容は変化してしまいます。 これは Clearメソッドにおいて FromPoint のように新しいオブジェクトで設定するか、ToPoint のようにオブジェクトはそのままで内容を変更するかの違いです。 メソッドの作り方としてはどちらの方法を採用すべきでしょうか。 Class を使う側からすれば、各Classごとに副作用が異なるのは困るので同じ基準でメソッドを作りたいのですが。 一般的にはメソッドを実行するたびに新しいオブジェクトを作るわけではないので(上記の例でいえば Clearメソッドで新しい Lineオブジェクトを作成するわけではない)下位レベルのオブジェクトについても新たにオブジェクトを作らないほうが考え方が統一されてよいとは思いますが。 しかし、下位レベルのオブジェクトを Nothing にする場合などはどうしても動作が異なってしまうので、どうすべきか混乱しています。