東西線の不思議な折り返し運転

日本で最も混雑する地下鉄路線として名高い東京メトロ東西線、

いや混雑するのはどちらかというと地上走行区間の多い東側ですが。

その中で南砂町駅の改良工事のために土日で一部区間運休で工事を行うことに。

いろいろ工夫をして完全に運休になるのは南砂町駅の前後1区間、東陽町~西葛西だけに抑えている。


ちなみに工事内容はホームを1つ増やして交互発着できるようにするというもの。

新しくなる東西線 南砂町駅、どう変わる? ホーム拡張+線路増設で乗り降りしやすくなる現場を見てきた (トラベルWatch)

東海道新幹線の品川・新横浜・名古屋・京都は全ての列車が停車するが、

列車を待っていると、右側・左側・右側とホームを交互に使っていることに気づく。

列車の乗降中から、後続の列車が反対ホームに入る準備が出来るので、列車を詰められるという仕組みである。

なぜ南砂町なのか? という理由は一見わからないが、南砂町駅の手前で列車が渋滞するらしい。

ラッシュアワーに撮影された動画を見ると、乗客を押し込むのに時間がかかってるっぽい。


それはそうとして気になったのは期間中の運行形態である。

下記の3区間に分けて運転されるという。

  • (JR中央線各停~)中野~東陽町
    • 中野→茅場町は5分間隔、茅場町→東陽町は10分間隔
    • 東陽町→中野は5分間隔
  • 西葛西~葛西 : 15分間隔で1駅間の折り返し運転
  • 葛西~西船橋(東葉高速鉄道との直通運転はなし)
    • 西船橋→葛西は15分間隔
    • 葛西→西船橋は7~8分間隔

西葛西は折り返しできない駅なので、西葛西~葛西は単線で1編成が往復している。

こうして1駅でも運休区間を狭めようとしてるんですね。


それはそうとして茅場町~東陽町と葛西~西船橋は往復で本数が違うんですよね。

当然、茅場町→東陽町、西船橋→葛西を回送列車として運行しているのだが、

特に回送列車の運行方法が特別なわけではなく、東陽町・葛西まで営業運転する列車と同じ経路で走っているらしい。

一体なぜこんなことをしているのだろうか?

調べてみると2つの意図があるのではないかと指摘があった。

1つは折り返し作業の時間を稼ぐためという指摘である。

東陽町・葛西とも1つのホームだけで折り返しをやるので短時間で折り返さないといけない。

回送列車として入れば折り返しにかかる時間を短縮できる。

1つのホームで5分間隔でやってくる列車の折り返しは間に合わないだろうが、

半分は茅場町で車内点検しておけば、乗務員交代して早々発車できる。


もう1つが運休区間に突っ込んでくる客を減らすためではないかとのこと。

今回の運休区間には代行バスが運行されるが、元々利用者の多い路線、

とてもバスでは間に合わないと考えられており、他路線での広域迂回や、

東陽町~南砂町の徒歩移動(およそ15分)を推奨しているところである。

広域迂回を考えれば茅場町・西船橋から他路線という形になる。

茅場町~東陽町、葛西~西船橋の途中駅では運休区間から遠ざかる方の本数が手厚いので、

運休区間を遠ざかる方向への利用を促せるという考えである。


2日以上運休での工事といえば、JR渋谷駅のホーム移設と銀座線渋谷駅の移設工事が思い浮かぶ。

JR渋谷駅については山手線・埼京線の線路をそれぞれ移設する形で、

埼京線運休時は山手線、山手線運休時は埼京線で補完する形だった。

銀座線渋谷駅については半蔵門線が平行しており、かなり代替できた。

それに比べると今回の東西線の運休はやっぱり大変である。

門前仲町~西船橋の途中駅にとっては他路線への分散が難しいのが実情で、

遠回りになっても茅場町・西船橋まで回り込んで迂回する形にならざるを得ない。

この区間の江東区・江戸川区・浦安市内の利用が旺盛であることが東西線の混雑の大きな要因だから当然ですけどね。


南砂町駅で交互発着を導入しても渋滞の先頭が動くだけでは?

という指摘はあったのだが、隣の東陽町駅には有楽町線支線(豊洲~住吉)の接続予定がある。

これにより東陽町駅の利用者が分散することへの期待はあるのではないか。

うーん……やっぱりどうなんだろ。

一応、交互発着以外にも折り返し運転にも活用できるというメリットはあるんですけどね。

地上走行区間は強風の影響を受けることがあるので、

地下区間の端、南砂町駅での折り返しができるメリットはありうると。

4回目接種の予定を決める

先日、新型コロナウイルスワクチンの4回目接種の案内が来た。

この4回目というのはオミクロン株対応ワクチンと言われているやつで、

従来の4回目対象者(高齢者など)に限らず、12歳以上の全住民が対象。

最後の接種との間隔によるが、僕の場合3回目接種が今年2月なので、

すでに5ヶ月以上経過しているということで早々送られてきた。


さて、これをいつ接種しようかという話である。

10月末から11月にかけて旅行で不在になるので、この前か後かというのがある。

この辺で接種できるならどっちでもいいかなと思ったけど、前に接種する方が都合は付けやすいかなという印象だった。

それで接種場所・開設日・予約状況を確認しようとしたら、今月中旬から「ファイザー社製のオミクロン株対応2価ワクチン(BA.4-5対応型)を使用」とのこと。

BA.1対応型とBA.4-5対応型というのは「いずれか早く打てるワクチンで」と厚生労働省は示しているので、あまり気にしなくていいらしいが、

段階的にBA.4-5対応型に切り替えられるので、こっちの方がいいんかなと。

単純に都合がいいところを選ぶとこっちになるって感じですね。


ちなみに今まで3回の接種はいずれもモデルナ製のワクチンである。

1~2回目は職場での接種だし、3回目は市内の集団接種はほとんどモデルナだった。

4回目はうってかわってファイザー製ばかりである。特に深い意味はなさそうだけど。

結局は接種しやすいところで選ぶとあまり選択肢はないんですよね。

どっちもmRNAワクチンだからあまり考えなくてもいいんですが。


1つ気になったこととしてインフルエンザの予防接種との関係がある。

実は今月下旬には職場で希望者対象のインフルエンザの予防接種がある。

うっかりインフルエンザがひどくなっても医者にかかれなくて苦しいでは困るので、

仕事抜けていくらか払って打ちにいこうと思ったが、どうなのか。

結論から言えば、新型コロナウイルスとインフルエンザに限っては考慮不要である。

新型コロナワクチンQ&A / 新型コロナワクチンとそれ以外のワクチンは、同時に接種することはできますか。 (厚生労働省)

mRNAワクチンは従来のワクチンとだいぶ違うので、他のワクチンとは13日以上の間隔を空けるのが基本である。

(一般的なワクチンでは注射での生ワクチン接種同士は27日以上の間隔を空け、不活化ワクチン・経口生ワクチンは前後考慮不要となっている)

ただし、新型コロナウイルスとインフルエンザだけはデータの蓄積があり、同時接種で問題ないとなっている。

同時接種できるということは前後関係を考えなくて良いというのと同義である。

近接することになったが特に問題はない。


うちの職場では新型コロナウイルスのワクチン接種で特別休暇が与えられることになっていて、4回目接種も同様との通知が出ていた。

市内で夕方に接種を受けるので、在宅勤務から早抜けで対応することにした。

インフルエンザの予防接種は30分の離席とかでも埋め合わせしろと言われるのに、

新型コロナウイルスは2時間早抜けしても有給扱いなのか……

と思うところはあるのだが、ルールはルールである。

ありがたい話ではあるんですけどね。平日日中なんて予約枠ガラガラだし。

本Blog(3代目)について

☆RSSについて
RSSは今まで通りと変わらないようにしてあります。
現在最新のRSSのURLは
http://hdmr.org/d/rss 
です。

☆コメントについて
コメントについては2011年4月よりDISQUSを利用しています。
誰でもコメントできますが、DISQUS・Google・Twitter・FacebookのIDやその他のOpenIDでのログインが必要です。
詳細な使い方については DISQUSのコメント機能の使い方 をご覧ください。
DISQUSではコメント以外に「いいね!」など残すことが出来ます。ぜひご利用ください。

☆リンクについて
自由にリンクを貼っていいです。各記事へのリンクもかまいません。
承認は取る必要もないです。

☆トラックバックについて

2021年3月をもって停止しました。

新入生もまたBlogerであった

ちょっと作業してます。このWebサイトにとって有益な作業です。
そんなわけでLibserverをいじってたのですが、Vine Linuxって4.2になってたんですね。
そんなわけでyumでアップデート。
便利でよろしいな。
さて、最近部に新入生が入ってきて、それはなんてことないことなのですが、
最近ミーティングがあって、Live Messengerの話が出てきました。
Windows Live Messengerは部の公式IMらしいです。
僕はYahoo! Messengerの方が好きなんだけど、まぁ部がそういうのだから仕方ない。
というわけでHotmail使わずにLive Passport取ってやってます。
で、彼らのメールアドレスを持って帰ってきて、招待を送りました。
礼儀正しく言えば向こうもわかってくれるので許可が返ってきました。
本名と表示名が違う混乱を避けるために、ちゃんと表示名も聞いてきたので理解しやすい。
といってもまだ名前と顔が一致しないんだけどね…
さて、Live Messngerには表示メッセージというのがあります。
ここに「レポート書いてるよ」とかいろいろ書けて便利です。
音楽情報垂れ流しにするとここに表示されます。
で、そこにいろいろ書いてくれると、ああこんなことやってるのかとよくわかるものです。
さて、それに関係してですが、HNをgoogle検索してみました。すると何人かはヒットしました。
Blogやってるんですね。ちょっとSkinが見にくい人とかいましたけど、
しかしいろんなことやってますねぇ…
ちょっとはその人のことを知れた気がする。けどまだ顔と名前が一致しない…
その中にはアニメの話書いてるなぁと思ったら急にレジストリが出てきたり、
なんかそんなまぜこぜの人もいた。このページもそうですよね。
僕がこんなことしてるってことは逆もあり得ると言うことだ。
そう、昨日までこのページを知らんかった人が急に見に来ると。
それはそれでいいことだ。ぜひRSS購読して更新を確認しましょう。

残念ながらこれはZ80ではありません

部にどういうわけか知らんけど、TK-85というワンボードマイコンがあった。
WikipediaによるとNECがかつてマイコン学習用に開発したものらしい。
で、TK-85はIntel 8085互換のCPUが載せてあるらしい。
ただ、8085はかの有名なIntel 8080に2命令追加されて、実行速度が速くなっただけ。
なので8080を扱ってる気分で扱えばいいでしょう。
というのは後からわかったことなのだが、ボードを掘り出してきたときはZ80互換のCPUが載ってるものだと思ってた。
Z80は8080よりさらに有名ですよね。8080の互換CPUなんだけど、すごい拡張された便利なCPU。
我々も実験で触れることになりました。だから掘り出してきたんだけど。
それで電源を入れて、操作方法がちんぷんかんぷんなのでちょっと調べて、
で、実験で使ったプログラムを打ち込むと予想通り動いた。
それで何も気にしてなかったんだが、他のプログラムを打つと動かん。
そのプログラムちょっと複雑なもので、IXレジスタが登場したりとZ80の拡張命令をフルに活用してる。
それから調べて8085の互換CPUだとわかったということ。なので8080でも動くプログラムを作って動かすのがよさそうです。
それなら8080のニーモニックを学習してそれで書いてアセンブリしろと言われそうだが。
我々はZ80のニーモニックに慣れてきたところなので、Z80の命令の8080から拡張された分を使わないことで手を打ってみようと思う。
そんなわけで使えない命令を隠して、使える命令の説明とフラグの変化をOOo Calcで書いて印刷した。
8080の命令は全部1バイトなので結構スマート。命令の数も思ってるより少ない。
これをみながらプログラムを書けばよさそう。
この範囲で書いてひたすらハンドアセンブリ、それで1バイトづつ打ち込んで動作させると。
手間ばっかりかかる。だけどなかなかおもしろいな。
実験で使ったZ80のボードは液晶ディスプレイまでついてるしリッチすぎる。
しかし、TK-85は結構シンプルで25のキーと7セグメントLEDが4つあるだけ、入力はともかく表示はかなり貧弱。
けど慣れるとなかなかおもしろいね。
さて、まぁそんなわけで家に帰ってきて、30分ぐらい考えて、エミュレーターでも確認してみて、
書いた8100h〜812Fhの間をバブルソートするプログラム。

        ORG 8000h
LD HL,8100h
START: LD D,H
LD E,L
LD B,(HL)
LOOP: INC HL
LD A,(HL)
CP B
JP NC,NEXT
LD (HL),B
LD B,A
NEXT: LD A,2Fh
CP L
JP NZ,LOOP
LD H,D
LD L,E
LD (HL),B
INC HL
CP L
JP NZ,START
HALT

HLをDEにコピーするのはHをD、LをEにするのを組み合わせてすれば正解だと思う。
これをエミュレータでアセンブルしたやつとハンドアセンブルしたやつを比較したら微妙に間違ってた。
やはりコンピュータはこういう仕事はよくやってくれる。
エミュレーターは時間が10秒ぐらいかかったけど、実機が本気でやったらどれぐらいかかるんだろう。

誰でも便利に電車を使えるようにするのはいいことだね

いつも電車に乗るとき、帰りは一番後ろの車両に乗ることが多い。
歩く距離が短いからなんだけどね。
で、車掌がよく見えるのだが、その横に指導員みたいなことを書いた腕章を付けてる人がいた。
どうも訓練みたいだな。結構頻繁にメモを確認してたし。
慣れるまではなかなか難しいだろうからね。きちんとやっておられたよ。
さて、乗り込んですぐ気付いたのだが、車いすの人がいた。
車掌に一番近いところに車いすの人は乗せられますね。
運転席付近に車いすスペースのある車両と、連結部付近に車いすスペースのある車両あるけど、
そんなの関係なしに、駅員は車掌の近くに乗せる。
連結部付近にあるやつは資源を有効に利用できてなくて残念だ。
そういえば乗り降りのとき駅員は板を持ってきますね。板なしでは段差がきついんだろうな。
あれはもしかして全部の駅にあるのかな。
どうしても車いすはスペース食うけど仕方ない。と思って奥の方に進もうと思ったら白杖を持った人がいた。
そういえば、よく駅で白杖を持った人を見るのだが、驚くほど器用に歩いておられるな。普段歩くところはよく理解しているのだろう。
さて、その方、どうも途中の駅で降りるらしくその支度をしておられた。
まぁぶつかっちゃまずいからちょっと移動しておいた。
それで、駅に着いた。ホームに駅員がいるのはさほど珍しいことではないからなんともおもってなかったのだが、
その駅員はどうもその人を誘導しに来たみたいだ。なるほどね−。
最近、近所の駅にエレベーターを取り付ける工事をするらしいという話を聞いた。
どうも法律で付けろということになってるらしい。
それにしてもすごい手間だし、金もかかるからねぇ…それに現状でもエスカレーターはあるし。
車いす対応じゃないけどね。
ただ、実際見てるとエレベーター以外はすごい手間みたいだな。
階段は言うまでもない。手動で車いすで段差を下る機械があるらしいんだが、すごい乗り心地が悪いらしい。
エスカレーターは車いす対応でも、エスカレーターを封鎖して、段を整えて、ゆっくり回さないといけないからどうも時間がかかる。
スロープは現実的ならいいと思うけど、高い段差をスロープで解決するのはおかしい話だ。
エレベーターなら単に足腰が弱い人でも使えて便利だからね。
しかし、あの駅に一体どうやって取り付けるんだろ…

CPUとお話しするようにプログラムが書ければいいのに

実験でZ80の機械語をいじる実験をやってたのだがZ80のボードはとても静かで、計算してるのかよくわからない。
メモリの中の値をいじるプログラムを書いて、その通り動いてるかメモリの中をのぞき見るということをやってる。
アセンブリ言語で見せられてもなんかわかりにくいわな。とくに比較とかジャンプとかのあたり。
さすがに、

ORG 8000H
LD A,(8100H)
LD HL,8101H
SUB (HL)
LD (8102H),A
HALT

みたいなのはわかりやすい。ORGはとりあえず無視。LD A,Bはa=b;みたいなもんだし、
(HL)や(8100H)なんかは、*hlや*(0x8100)みたいにアドレスを参照してるんだろう。2つ目の書き方は変だけど。
SUB (HL)はa-=*hl;という発想でいいと思う。どうも計算の類はAの値を変えるものらしい。
ここで、SUB 01H(a-=0x01;)はいいのだが、SUB (8101H)はだめ。
それをしたいなら、8101Hを一旦HLに入れるか、(8101H)をBなどに入れないとダメ。
こんな風に書けても、ある命令とない命令があるからね。アセンブラがエラーを出してきたりもする。
実験にアセンブラは使ってないけどね。表とにらめっこしてやってた。まさにハンドアセンブル。
他にない命令というと、LD (8100H),(8101H)のような命令はない。これはひどい命令だ。
LD (8102H),Aはあるけど、LD (8102H),Bのような命令はない、けどLD (HL),Bはある。
まぁアドレス扱うときはHLに入れるのが無難そうだな。横着すんなということかもしれん。
さて、このソース、

      ORG 8000H
LD B,64H
LD HL,8600H
XSET: LD A,(HL)
JP NEXT
LOOP: CP (HL)
JP C,XSET
NEXT: INC HL
DEC B
JP NZ,LOOP
LD (8664H),A
END

スパゲッティプログラムやね。しかしアセンブリ言語だとこれが限界。
まず、Bに0x64、HLに0x8600を入れましたと、それでまずAに(HL)を入れる。
それでNEXTラベルに飛んでHLを1増加、Bを1減少させる。
INCやDECはb–;のような動作をする。どうもINC (HL)のような書き方もできるらしい。ニーズあるか知らんけど。
それで、JP NZ,LOOPというのは、最後の計算が0でない(NZ)ならばLOOPラベルに飛べ。
すなわちBの値が、DEC Bで0x64,0x63…と減らされて、0x00となるまでひたすら繰り返すと言うこと。
JP NZ,LOOP〜LOOP間を0x63回繰り返すと言うことになりそうだな。
それで、CP (HL)とあるが、これはちょっと不思議な命令。
ADD Bとか、DEC Bとか、そういう計算をすると、答えが0だったらZフラグを立てたり、桁あふれがあればCyフラグを立てたりするらしい。
ただ、CP命令は計算はするが値は変えないという、けどフラグは立てるというものらしい。
CP (HL)はAの値が変わらないDEC (HL)と思えばいいと思う。
それで、JP C,XSETで繰り上がりがないか確認して、あればXSETに飛ばされて、Aに(HL)を入れて、NEXTに飛ばされて…
というものなのだが、一体何をするものなのかというと、8600H〜8663Hの間の値を符号なし1ビット整数と考えて一番大きな値を抜き出すプログラム。
A-Bで桁あふれがあるというのは、B>Aだかららしい。だからこんなやり方をするのだと。
それはいいんだが、課題に、符号ありのときどうすればいいか考えろってのがある。
で、どうも符号ありなら、JP C,XSETをJP M,XSETにすればよさそうだと思った。
これはA-B<0ならSフラグが立って、MにすればSフラグが立ってれば飛ばされるはず。
それでうまくいくと思ったのだが、実際は桁あふれがある加減でなかなかうまくいかない。
こういうのを解決する方法があるんだろう。
それでCのコンパイラやらはそれを利用してどうやってやるか考えてるんだろう。
ありがたい話だ。すばらしい通訳だな。

すべての始まり、Objectクラス

Objectクラスには3つの仮想メソッドがあるらしい。
public virtual string ToString();
public virtual bool Equals(object obj);
public virtual int GetHashCode();
今まで何度かIFormattableを実装したことはあったが、ObjectクラスのToStringメソッドのことはすっかり忘れていた。
すべてのクラスは突き詰めればObjectクラスを継承していることになる。
継承するクラス名を書かなければObjectクラスを継承したことになる。
そんな都合でObjectクラスにあるメソッドはすべて持っているのだが、
この3つはオーバーライドしないと都合が悪い。
ToStringはオーバーライドしないと、hidemaro.myintのようにクラスの名前が返ってきてしまう。
これの要領はIFormattableのToStringと似てるけど、引数が違うからね。Objectの方は引数なし。
このObjectのToStringのオーバーライドはIFormattableを実装するために自作したToStringを利用するのが便利だろう。

public override string ToString() {
return this.ToString("d", null);
}

こんな感じ。
Equals・GetHashCodeはまず間違えなく正しくない値を返してくる。
で、まずEqualsの方は、メンバ変数をひたすら比較すればいい。

public override bool Equals(object obj) {
foo other = (foo)obj;
return this.a==other.a&&this.b==other.b;
}

という調子。まぁこれは何となくわかる話。
GetHashCodeはよくわからんのだが、どうも同じ意味を持つインスタンス同士は同じ値を返すべきらしい。
で、紹介されてる方法を参考に書くとこうするといいらしい。

public override int GetHashCode() {
return this.a.GetHashCode() ^ this.b.GetHashCode() ;
}

XORでメンバ変数のそれをひたすらくっつければいい。
なので自作クラスがあるならそれにも同様にGetHashCode()をオーバーライドしておきましょうと。
さて、そんな具合でやってました。
しかしVisual Studioは素晴らしいね。
overrideと打ってスペースを1つ入れると、オーバーライドできるメソッドのリストが出てくる。
楽ですねぇ。まぁわからなければオブジェクトブラウザで探せばいいだけだけど。

値渡しとクラスのインスタンスの罠

最近C#の話ばっかりだが、部のページでOOP特集を書いてるものでいろいろ調べてたんだ。
さて、そういえばC#の引数は値渡しという話があったがよくわからないのでいろいろ試してみた。
まずこんなクラスを作ってみた。

class myint : IFormattable {
private int v;
public myint(int v0) { v=v0; }
public void incl() { v++; }
public string ToString(string format, IFormatProvider formatProvider) { return v.ToString(format, formatProvider); }
}

中にintを1つ格納しただけのクラスだな。クラスというところは重要、構造体ではない。
だいたい動作は予想できると思うけどね。
その上でこんなものを動かしてみた

int i=10;
myint mi=new myint(i);
Console.WriteLine("{0}", i);
mi.incl();
Console.WriteLine("{0}", i);
Console.ReadKey(false);

さて、これを動かすと両方10が返ってきた。
手順としてはまずmyintのインスタンスを作成するが、このときiの中に入った10という値を変数vに代入した。
なのでこのとき変数vは10を示している。当然ここの値を1増やしたところでiには影響がない。
値渡しというのは仮変数(であってるのか)のv0は、引数に書いた変数、今回はi、を丸ごとコピーするということ。
だから、仮変数のv0と引数に書いた変数iは無関係になっていることはわかるとおもう。
さらに構造体(値型)の代入は中身を丸ごとコピーすることで行うので、コンストラクタでvに代入した時点で仮変数のv0とは無関係。
そのv0をinclメソッドでいじろうがこれも無関係。
だからinclメソッドを動かす前後でiの値は変わってない。これが構造体の特徴ですね。
さて、では中に入れる変数をクラスのインスタンスにしてみよう。

class mymyint : IFormattable {
private myint v;
public mymyint(myint v0) { v=v0; }
public void incl() { v.incl(); }
public string ToString(string format, IFormatProvider formatProvider) { return v.ToString(format, formatProvider); }
}

さっきとだいたい同じものだな。違うのはmyintを納めたものであるということ、
それにともなってinclメソッドがそこからさらにmyintのインスタンスのinclメソッドを呼び出している。
これでもってこんなものを動かしてみる。

myint mi=new myint(10);
mymyint mmi=new mymyint(mi);
Console.WriteLine("{0}", mi);
mmi.incl();
Console.WriteLine("{0}", mi);
Console.ReadKey(false);

まぁさっきとあまりかわらない。結果は前が10、後が11。
なぜこうなるのかという話だが、クラスのインスタンスの変数はCで言うところのポインタだ。
なので、miには1行目で、たとえば「甲地を見よ」と書いたものを代入されたようなものだ。
その上でmmiのコンストラクタに引数として渡した。値渡しなのでコピーされると言った。
しかしコピーされたのは、「甲地を見よ」ということだけ。
だからもしこのコンストラクタの中でその仮変数v0の中身にコンストラクタで全く新しいインスタンスを代入して、
たとえばv0が「乙地を見よ」に変わったとしても、値渡しだから、引数に書いたmiには反映されない。
けど今回はそんなことせず、そのv0をただvに代入しています。
こうなると、miとvはそれぞれ同じ場所を示していることがわかりますよね。
その上で、vのinclメソッドを動かします。すると、vの内容だけ変わります。vの値は変わりません!
その上、vもmiも指していることは同じ。だからmiの値は変わってないのに内容はさっきの動作で変わってしまっている。
その結果、miの内容を表示させたら、1増えた11になってたわけです。なるほど。
もしvの内容とmiの内容を無関係にしたければ、改めてvの内容を作って、miと同じ内容をコピーしないといけない。
このためにコピーコンストラクタというのが欲しくなるわけか。
さて、この特徴を知ったら、foreachで内容が変えられるような気がしてきました。
そこでこんなクラスを自作しました。完璧じゃないけどある程度は動く。

class changeable<T> {
private T _v;
public changeable(T v0) { _v=v0; }
public changeable(changeable<T> v0) { _v=v0._v; }
public void change(T v0) { _v=v0; }
public static implicit operator changeable<T>(T v0) { return new changeable<T>(v0); }
public static implicit operator T(changeable<T> v0) { return v0._v; }
}

Nulltable構造体を参考に作ってみました。まぁこれはクラスですが。
このクラスのインスタンスのchangeメソッドで中身を書き換えることができる。
というものなのだが、これがどう有用かは見て欲しい。

changeable<string>[] strs=new changeable<string>[] { "ABC", "DEF", "GHI" };
foreach (changeable<string> cstr in strs) { cstr.change(cstr+"!"); }
foreach (string nstr in strs) { Console.WriteLine(nstr); }

無理矢理一行で書いたから読みにくいね。
で、changeable<T>の配列を作りました。Tからchangeable<T>には暗黙的に変換されるのでこれでいいです。
この上で、foreachで1つづつ回してもらう。
foreach内でその仮変数に代入するということは許されない。まぁ意味ないからね。
普通のstringの配列は、「甲地を見よ」などがいくつか入っていて、
foreachでは毎度、「甲地を見よ」というようなことを仮変数に入れて回してくれる。
だから内容を読むことは自由自在だ。だけど、仮変数を変えても意味はないね。
そこで、この「甲地を見よ」というものを収納したchangeable<T>のインスタンスの配列。
そこには別の「乙地を見よ」などが書いてあって、これを毎度回してくれる。
その上で、乙地を見て、乙地に書いてある、「甲地を見よ」を「丙地を見よ」に書き換えたとする。
これがchangeメソッド。確かにこれは問題じゃない。だって仮変数は変えてないから。
それでこのforeachのループが終わった後、回した配列、今回ならstrsを改めて観察する。
当然だけど、「乙地を見よ」などと書いてあるのは変わってない。
だけど乙地を見てみると、「甲地を見よ」が「丙地を見よ」と内容が変わっている。
というわけで、指すところは変えてないのに、そこから指す場所を変えて、内容を変えてしまったと。
おもしろいね。foreachをこうやって使えるとは。

LINQという名のIEnumerable革命

テストのためにVisual C# 2008 Express Editionを入れてみた。
これは.NET Framework 3.5に対応したプログラムが書けるのでいろいろやってみた。
まずデリゲートの簡略化というのが1つある。ラムダ式と言うらしい。
デリゲートの型としてFunc<T,TResult>などが導入された。

Func<double, double> v = 
t => { return 100 * Math.Sqrt(2) * Math.Sin(2 * Math.PI * 60 * t); };

数学の関数を定義するかのように簡単にデリゲートが作れると言うこと。
これはvという名前で引数にdouble1つ、返り値にdoubleを返す関数のデリゲートということ。
引数の名前を1つならt、2つ以上なら(vrms,t)のようにして、=>とやって右にいろいろ書けばいい。
{}でくくって複雑な動作を書いてもいいし、もっと簡略化して返り値を直接書いてもいい。
Func<double, double> f = t => t*2;という風にね。というかこれがラムダ式の本義ですね。
これはデリゲートの創作意欲が出てくる便利な書き方だ。
いままでも匿名メソッドってのでデリゲートは作れたけど匿名だったからなぁ…おもしろくない。
さて、これを使うことでいろいろおもしろいことが出来ます。
で、LINQというのがあるのだが、僕はこれをIEnumerable革命だと思っている。
IEnumerableは繰り返し可能、すなわちforeachできると取り決めをするインターフェース。
データベースをIEnumerableを実装したクラスのインスタンスで取り扱うというのがLINQの考えらしい。
で、データベースを操作するようにIEnumerableを操作できるという機能をたくさん搭載した。
けど、IEnumerableはインターフェース、インターフェースは動作を決めることができない。
なので抽象クラスみたいに機能が追加できるわけじゃない。
そこで考えられたのが拡張メソッドかもしれない。

System.Linq.Enumerable.Where<classmate>(foos, x => { return x.id % 2 == 0; });
foos.Where(x => { return x.id % 2 == 0; });

本来上で書くべきことを下の方法で簡略化できることなんだが、なんのことだかさっぱり。
どうもよくわからんのだがそういう特別な静的メソッドを定義してあるらしい。それを拡張メソッドと言うようだ。
拡張メソッドはとりあえず自作しないので、これを使うことを考えよう。
どうもLinqのおかげで、IEnumerableを実装したクラスに新しくいろんな機能が備わった。
IEnumerableを実装したクラスでもっともポピュラーなのは配列だな。

classmate[] foos = new classmate[] { 
new classmate(1,"浅田"), new classmate(2,"井上"),new classmate(3,"尾崎"), new classmate(4,"川上")};
var myfoos = foos.Where(x => { return x.id % 2 == 0; }).Select(x => { return x.name; });
//var myfoos = from foo in foos where foo.id % 2 == 0 select foo.name;
foreach (var foo in myfoos){
Console.WriteLine(foo);
}

というわけでこんなソースコードを作ってみました。
まず配列を作りました。classmateというクラスは自作しましたよ。本当にこんな名前のクラスメイトがいるかは知らないけど。
int型のid、string型のnameというプロパティを持ってる。ちなみにgetしかないので読み取り専用。
で、次の書き方が新しい書き方。まず型類推のvarを使っている。
まぁあんまり型類推は使いたくないけどなぁ…けど何なのか直感的じゃないもので。
後に説明するけど、ここのvarにはIEnumerable<string>を入れれば正解。
さて、件の拡張メソッドにはIEnumerableなのを加工する機能がたくさん入ってる。
それでこれはSQL文に似せて書ける。けどなんか僕は直感的じゃないからあえて使わない。
ちなみにそのSQL文に似せて書いた例はコメントアウトしてあるからわかる人は見ればいい。
なので元の拡張メソッドを呼び出して書くことにする。
この拡張メソッドにはSQL文のWHERE文に相当するWhereメソッドやらいろいろ用意してある。
で引数にはFunc<classmate,bool>なやつを用意すればいい。
この引数で与えたデリゲートでもって条件を指定するわけだ。
そんなデリゲートをラムダ式で簡単に自作できる。便利ですな。
今回は理解しやすかったから=>{}で書いたけど、この程度ならx=>x.id%2==0と書いた方がいいか。
このWhereメソッドはIEnumerableなのから条件を満たすものを選別してくれるというメソッド。
IEnumerable<classmate>を実装しているclassmate[]のときの返り値はIEnumerable<classmate>。
これをさらにSelectメソッドで加工。これもSQL文のSELECT文に由来。
引数にはFunc<classmate,TResult>(TResult任意)を渡せばいい。
今回はここから名前を取り出すデリゲートを作成してやりました。
なので、引数に渡されたのはFunc<classmate,string>、これで1つ1つ加工していくと。
もちろんもっと複雑なデリゲートを作成してもいい。名前の文字の順番を反転させるとか。
x => { char[] cs = x.name.ToCharArray(); Array.Reverse(cs); return new String(cs); }
にすればできるよ。
で、これで加工されて、返り値はIEnumerable<TResult>、今回はIEnumerable<string>ですね。
あとはこれをforeachでループに回した。
これを配列に変換することもできる。myfoos.ToArray();の要領でやればいい。
これも拡張メソッドのおかげ。
というわけでなかなかおもしろい機能が追加されたなぁと言う印象。
これはデーターベースと組み合わせてこそ便利なんだろうけど、特にそんな計画はなし。
だけど配列やコレクションの整理という意味では結構便利だなぁと思った。
まぁけど、.NET Framework 2.0では使えないのが残念。.NET Framework 3.5はいつになれば普及するのだろうか。