質問者
List<値型>の中の値を変更するには

質問
すべての返信
-
ちよっと間違ってました。幅と高さはかえないです。100,100,10,10にするスマートな書き方はないでしょうか、ということです。
RectangleF [] ar2 = new RectangleF[1];
ar2[0] = new RectangleF(0,0,10,10);
ar2[0].Offset(100,100);RectangleF rcf = ar2[0];
これだとrcfは100,100,10,10になるんですよね、、、。間違いやすいです
どういうことでしょうか?理解できませんでした。期待している動作は何で、実際何になっているから困っているのですか?
-
List<RectangleF> ar1 = new List<RectangleF>();
ar1.Add( new RectangleF( 0,0,10,10) );
ar1[0].Offset( 100,100 );
RectangleF [] ar2 = new RectangleF[1];
ar2[0] = new RectangleF(0,0,10,10);
ar2[0].Offset(100,100);RectangleF rcf1 = ar1[0]; // X=0,Y=0,WIDTH=10,HEIGHT=10
RectangleF rcf2 = ar2[0]; // X=100,Y=100,WIDTH=10,HEIGHT=10質問の趣旨はrcf1もX=100,Y=100,WIDTH=10,HEIGHT=10にするスマートな書き方
はないでしょうか、ということです。
-
なかなか難しい問題ですね。Hongliangさんが書かれているように、値型の内容を書き換えるようなメソッドがあるのが紛らわしいという考えもありますが、オブジェクト指向的にはそのようなメソッドはあってもよいとは思えます。> スマートな書き方はないでしょうか、ということです。値型はコンテナから取り出した時点で異なるインスタンスのコピーであるので、格納されているインスタンスを直接操作することができない時点で、「取り出す」「変更する」「格納しなおす」という手順がどうしても必要です。変な記述としては、
class=inlineLink onclick="window.open('/MSDN-JA/User/Profile.aspx?UserID=68882&SiteID=7', target='_self')">ar1 = ar1.ConvertAll(delegate(RectangleF src)class=inlineLink onclick="window.open('/MSDN-JA/User/Profile.aspx?UserID=68882&SiteID=7', target='_self')">{class=inlineLink onclick="window.open('/MSDN-JA/User/Profile.aspx?UserID=68882&SiteID=7', target='_self')"> src.Offset(100, 100);class=inlineLink onclick="window.open('/MSDN-JA/User/Profile.aspx?UserID=68882&SiteID=7', target='_self')"> return src;class=inlineLink onclick="window.open('/MSDN-JA/User/Profile.aspx?UserID=68882&SiteID=7', target='_self')">});class=inlineLink onclick="window.open('/MSDN-JA/User/Profile.aspx?UserID=68882&SiteID=7', target='_self')">
みたいな方法もあるでしょうけど、まったくオススメできないです。 -
みなさん、どうもありがとうございます。
List<RectangleF> ar1 = new List<RectangleF>();
ar1.Add( new RectangleF( 0,0,10,10) );
ar1[0].Location = new PointF(100,100); これはエラーこれがコンパイルエラーになるのだから、スジとしてはOffsetもエラーになるべき、と思いますが、、、。
List<RectangleF> ar1 = new List<RectangleF>();
ar1.Add( new RectangleF( 0,0,10,10) );
RectangleF rc = ar1[0];
rc.Offset( 100,100 ); // void関数なのだ
ar1[0] = rc;やはり、これしかないようですね。いまのところは。
-
上の Lady.BUGさんのコメントがスルーされてしまっているみたいだけど
> ar1[0].Location = new PointF(100,100); これはエラー
は,ar1[0] の時点ですでに要素のコピーが返ってきているから,
その地点で別物になってしまっています。
(エラーになっているのは,一時的な値型を変更しようとしているからなんだけど,
たとえできたとしても,別物だから意味がないですよね)例えば,int のような同じ値型を扱ったとしても,
C++でいうところの vector の [] は,参照を返す形(int&)だけど,
BCL の List の [] は,値のコピーが返ってくる形(int)になっているため,
動作が異なるんですよね...。# そもそも,CLR で値型の参照(いわゆる int& のようなもの)が可能なのか?
# なぞですが... -
稍丼 さんからの引用 # そもそも,CLR で値型の参照(いわゆる int& のようなもの)が可能なのか?
# なぞですが....NET では、マネージドポインタ (int&) があるので可能です。ただし、CLSCompilantではなくなりますし、マネージドポインタはC#からはパラメータ以外では直接利用できないので難しいです。C#でマネージドポインタを扱えるのはパラメータだけで、キーワード ref を利用します。イメージ的には、
(A)List<ref int> numberList = new List<ref int>;numberList.Add(new int(5));numberList[0] += 2;// もしくはunsafeの構文をまねて *(numberList[0]) += 2 かな?(B)public class RefList<T>{public ref int this[int index] { get; set; }}
みたいなかたちで扱えればよいんでしょうけど、これはこれで「格納されている値型が、どこで確保されたメモリブロックへのポインタなのか?」をコンシューマが予測するのが非常に難しくなると思います。# スタックに確保された値を add したらその時点でヒープにコピーが生成されるとか、コンパイルエラーになるようなルールも必要かもしれないですねこの続きは blog で(ぇ