忍者ブログ

Memeplexes

プログラミング、3DCGとその他いろいろについて

"Orcas"とC# 3.0 その1 自動実装プロパティ

遅ればせながら次期Visual Studio、
"Orcas" Express Editionをインストールしてあそんでみました。

インストールしてさっそく起動してみると、
・・・特に2005と変わらないように見えます。
orcasStartPage.JPG
しいて違うところをあげるならタブの色がよりLunaっぽく、
かっこよくなっているということくらいでしょうか。

とりあえずプロジェクトを作って何かやってみることにしました。
orcasNewProject.JPG
当たり前ですが作れるプロジェクトの種類が2005より少ないようですね。
ともかく、一番単純な、コンソールプログラムで遊ぶことにしました。

今回の目玉はLinqらしいので
おいしいものは最後に取っておくと言う意味で
まずは地味な機能を使うことにします。
なんでもC# 3.0ではプロパティの宣言が
簡単になったとの事ですので。(自動プロパティ)

using System; struct Vector2 { public float X { get; set; } public float Y { get; set; } } class Program { static void Main(string[] args) { Vector2 vector = new Vector2(); vector.X = 0; vector.Y = 1; Console.WriteLine("x = {0}, y = {1}", vector.X, vector.Y); } }

結果はこうです:

x = 0, y = 1

Rubyのように、プロパティを宣言するだけで、
変数の宣言の必要は無いらしいです。
それにしてもこのプロパティの書き方はインターフェースで
プロパティを宣言するやり方に似ています。(伏線)

次にコンストラクタを書いてみました。
わざわざ2行使ってプロパティに値を代入するのは
面倒に思えたからです。
しかし、失敗しました

Compile Error!

using System; struct Vector2 { public float X { get; set; } public float Y { get; set; } public Vector2(float x, float y) { this.X = x; this.Y = y; } } class Program { static void Main(string[] args) { Vector2 vector = new Vector2(0, 1); Console.WriteLine("x = {0}, y = {1}", vector.X, vector.Y); } }
"The 'this' object cannot be used before all of its fields are assigned to"
とでました。他にもそれに関連したエラーが2つ。
どうやらコンストラクタ中でプロパティに代入してはいけないようです。

「だったら一体どうやって初期化するんだ」という気になります。
調べてみると、オブジェクトを初期化する特別な方法も出たそうで、
それを使えばよさそうです。
using System; struct Vector2 { public float X { get; set; } public float Y { get; set; } } class Program { static void Main(string[] args) { Vector2 vector = new Vector2 { X = 0, Y = 1 }; Console.WriteLine("x = {0}, y = {1}", vector.X, vector.Y); } }
すばらしい・・・。

ものすごく簡潔です。
引数をとるコンストラクタを書く必要がありません。

もしかするとWindows Presentation Foundation(WPF)で
引数をコンストラクタにもつクラスが少なかったのは
これへの布石だったのかもしれません。
単に怠慢でコンストラクタを用意しなかったのではなく、
必要なかったから用意しなかっただけなのかもしれませんね。
引数(?)の意味もより明確になっています。

なんとなくCωの初期化の仕方を思い出します。

次に気になるのは「読み取り専用のプロパティを作れるのかどうか」
ということです。

そこで確かめるために次のようなコードを書いてみましたが、
失敗です。

Compile Error!
using System; struct Vector2 { public float X { get; } public float Y { get; } public static Vector2 Create(float x, float y) { return new Vector2 { X = x, Y = y }; } } class Program { static void Main(string[] args) { Vector2 vector = Vector2.Create(0, 1); Console.WriteLine("x = {0}, y = {1}", vector.X, vector.Y); } }
"'Vector2.X.get' must declare a body because it is not marked abstract or extern.
 Automatically implemented properties must define both get and set accessors."

・・・だそうです。どうもabstractやexternのプロパティと勘違いされたようです。
実際書き方は同じですし。
と言うか書き方が同じと言うより意味的に同じなのかもしれません。
エラーメッセージによると、自動プロパティは
自動的に実装される」と言う意味らしいからです。

ネーミングの由来は納得しましたが
だからと言って問題が解決したわけではありません。
やはり調べてみると、盲点でした、setの前にprivateをつけるらしいです。
using System; struct Vector2 { public float X { get; private set; } public float Y { get; private set; } public static Vector2 Create(float x, float y) { return new Vector2 { X = x, Y = y }; } } class Program { static void Main(string[] args) { Vector2 vector = Vector2.Create(0, 1); Console.WriteLine("x = {0}, y = {1}", vector.X, vector.Y); } }
この方法はプロパティを手動で実装するときと同じですが、
その場合はたいていprotected set...となります。
まさかprivate setになるとは・・・完全に盲点でした。

しかしおかしな話です。
上のブログでも言われていますが、private setくらい
自動的に補完して欲しいものです。
setできないのならプロパティに意味なんて無いわけですから。
(そしてこの疑問に対する回答もやはり要領を得ません。)

将来は改善されるといいのですが・・・

拍手[0回]

PR