R.Tanaka.Ichiro's Blog

主にC# な話題です

目次

Blog 利用状況

ニュース

暗黙的型付け(その2)

http://blogs.wankuma.com/rti/archive/2007/12/25/114456.aspx
暗黙的型付け

上記のタイトルのコメントですが、思ったよりも濃い反応をいただいたため、返信が少々長くなってしまったので、1タイトルとして独立させることにしました。
前回の論点ですが「3番目のコードが有用だと思う人は、2番目のコードも許容できるのではないか?」と言う内容でした。

・・・結果、そうではないという意見が多かったように思います^^;


double amount = this.GetAmount();
this.SetAmount(amount);


var amount = this.GetAmount();
this.SetAmount(amount);


this.SetAmount(this.GetAmount());


我々が、3番目のコードを読む限りでは、this.GetAmount() から何らかの値が返ってきて、それを SetAmount() メソッドに渡しているのだと認識するかと思います。
その「何らかの値」という中間結果を amount という変数を設けて明示したものが1・2番目のコードということになります。

1番目のコードは、double 型である amount に値を代入しています。
しかし、GetAmount() が返す値は、本当に double 型なのでしょうか?
ひょっとして、キャストの不要な型を double で受け取っているのかもしれません。
このコードを見ただけでは、それはわかりません。
しかし、amount が double 型であること、そして SetAmount() メソッドに double 型の値を渡せていることは明白です。

2番目のコードは、amount の型は GetAmount() が返す型と推論されて、その型として振舞われます。
つまり2番目のコードで示す amount は「GetAmount() が返す型と同じ型」という型名だと考えることができます。
そして「GetAmount() が返す型と同じ型」に格納された値を、SetAmount() メソッドに渡せていることは明白です。


GetAmountが返す型と同じ型 amount = this.GetAmount();
this.SetAmount(amount);


3番目のコードは、2番目のコードと比較して、amount 変数を介さないという違いを除いて2番目のコードと同じ意味になります。

以上が、ソースコードの表現として、3番目のコードに近しいのは、1番目よりも2番目であろうと考えている点についての補足です。

ところで2・3番目のコードで言うところの「GetAmount() メソッドが返す型と同じ型」という解釈は、結局ところ型を常に意識しているという点で今までと何も違いは無いように感じます。
メソッド間で値を受け渡すコードを記述する際に、問題があるかどうかを調べる必要がありますが、これは上記3つのコード全てに同様です。
同時に、このことは1番目のコードで double 型だとされている amount 変数を介してデータの受け渡しができることに安心感が持てる理由でもあります。

ちなみに僕なりの ver を使うべき場面と、そうでない場面の使い分けですが、

現時点での結論

は「使えるところは使え」です。
理由は、そもそも C#3.0 の言語仕様は、使うべきところで無いところは、var が使えないように設計されていると感じるからです。
例えば、僕は for 文も下記のように書いています。


for (var i = 0; i < hoge.Count; ++i)


しかし、以下のコードのように型推論できない場合は、型を明示します。


foreach(DataGridColumn x in this.grid.Columns)


最も、ジェネリクスによるコレクションが更に主流になってくれば、上記のように書かなくてはいけないケースも少なくなって来るでしょう。
その他は、こんな感じで書いています。


var b = (byte)5;
var d = 4m;
var i = 5;
var c = (DataGridColumn)this.grid.Columns[0];


結局、var を用いる場合、用いる側(あるいは読み手)は、何に推論されるのかを知った上で書く(読む)必要があると思うのです。
これは結果的に var を用いても常に型を意識しなければならないことに変わりは無い、と言うことを示しているのではないでしょうか。
このことは、以下の x の型についても例外ではないかと思います。


var x = new { Id = GetId(), Name = GetName(), Age = GetAge() };


まあ、上記が前記事のコメント中で言うところの「脳内変換の慣れ」になってくるのだと思いますが、これは先のメソッドの受け渡しの「中間結果」で何となく皆さん鍛えられているんじゃないかなぁ、と言うのが僕の意見です。

#・・・という結論じゃ駄目ですか?^^:

投稿日時 : 2007年12月26日 15:34

Feedback

# re: 暗黙的型付け(その2) 2007/12/26 16:25 NyaRuRu

私の場合,
for (var i = 0; i < hoge.Count; ++i)

var b = (byte)5;
var d = 4m;
var i = 5;
は多分書きません.

その代わり,
int id = GetId();
string name = GetName();
int age = GetAge();
から
var person = new { Id = GetId(), Name = GetName(), Age = GetAge() };
へのリファクタリングは確信犯的に多用しそうな気がします.

# re: 暗黙的型付け(その2) 2007/12/26 16:30 シャノン

ちなみに俺も、どちらかといえばアンチvarです。
理由は、これ

> 結局、var を用いる場合、用いる側(あるいは読み手)は、何に推論されるのかを知った上で書く(読む)必要があると思うのです。

のコストが大きいから。

# re: 暗黙的型付け(その2) 2007/12/26 16:32 NyaRuRu

>シャノンさん

ということは,

int id = GetId();
string name = GetName();
int age = GetAge();



var person = new { Id = GetId(), Name = GetName(), Age = GetAge() };

に書き換えるとやっぱり嫌われるのでしょうか?

# re: 暗黙的型付け(その2) 2007/12/26 16:44 渋木宏明(ひどり)

>1番目のコードは、double 型である amount に値を代入しています。
>しかし、GetAmount() が返す値は、本当に double 型なのでしょうか?
>ひょっとして、キャストの不要な型を double で受け取っているのかもしれません。
>このコードを見ただけでは、それはわかりません。

これはNOじゃない?
C++ が警告しないケースでも、C# では警告対象でしょ?

>しかし、amount が double 型であること、そして SetAmount() メソッドに double 型の値を渡せていることは明白です。

これもNO。
SetAmount() が object を受け取る場合もあるはずなので。

とすると

>そして「GetAmount() が返す型と同じ型」に格納された値を、SetAmount() メソッドに渡せていることは明白です。

は、そう確実に保証されたものではないんじゃないかと。

# re: 暗黙的型付け(その2) 2007/12/26 16:50 シャノン

> NyaRuRu さん

そこで匿名型に書き換える必然性があるのでしょうか?
無いのなら嫌います。

# re: 暗黙的型付け(その2) 2007/12/26 16:57 NyaRuRu

>そこで匿名型に書き換える必然性があるのでしょうか?

なるほど確かに書き換える「必然性」は無いかもしれませんね.

では書き換えではなく新規記述の場合はどうでしょうか?

# re: 暗黙的型付け(その2) 2007/12/26 16:59 シャノン

struct Person
{
int Id;
string Name;
int Age;
}

Person person = new Person { Id = GetId(), 以下略 };

と比べて、明らかな優位性が無ければ嫌います。

# re: 暗黙的型付け(その2) 2007/12/26 17:00 シャノン

public抜けてた。

# re: 暗黙的型付け(その2) 2007/12/26 17:06 NyaRuRu

なるほどなるほど.
確かに明らかな優位性はないかもしれませんね.
Id と Name は使うが Age を使わない場合にも,デフォルト値で埋めるべきかとか,コンストラクタを何種類用意すべきかみたいなので悩むのは個人的に嫌いなのですが,まあ明らかな優位性というほどでもなさそうなので,デフォルト値で埋めたりコンストラクタを何種類も用意した方が良さそうですね.

# re: 暗黙的型付け(その2) 2007/12/26 17:08 NyaRuRu

あと必要と分かってからソースコード上を移動して Person を定義し,また元の場所に戻ってきて続きを書くのも嫌いなのですが,これもまあ明らかに不利な点とは言えない気がします.はい.

# re: 暗黙的型付け(その2) 2007/12/26 17:10 NyaRuRu

そういえばpublicな型定義に変更を行うとき,影響をチェックするのも大変かもしれませんが,これも最近はリファクタリングツールが発達しているので心配なさそうですね.

# re: 暗黙的型付け(その2) 2007/12/26 17:11 シャノン

というか、匿名構造体にまとめる理由は何? ということなのですよ。
その構造体まるごとどこかに代入できるわけじゃないし(object型を除く)。

別に変数バラバラでもいいじゃないとか。

> Id と Name は使うが Age を使わない場合にも,デフォルト値で埋めるべきかとか

じゃあ Nullable とか。

> コンストラクタを何種類用意すべきか

クラスならともかく、構造体なら全フィールド public でもいいと思うし、プロパティが好きなら自動プロパティもありますし。

# re: 暗黙的型付け(その2) 2007/12/26 17:12 シャノン

> そういえばpublicな型定義に変更を行うとき

varと比較するなら、構造体自体はprivateでしょう。
publicを付け忘れたのはメンバです(いつも忘れる)。

# re: 暗黙的型付け(その2) 2007/12/26 17:15 NyaRuRu

「最新ビルドの Person にあのフィールド/メソッドあったっけ?」みたいなのを憶えておくのも大変な気がしますが,これも IntelliSense やクラスブラウザがサポートしてくれると.

こうやってみると言語の微妙な部分ってあらかたツールが何か埋めてくれてますね.おもしろい.

# re: 暗黙的型付け(その2) 2007/12/26 17:16 シャノン

> あと必要と分かってからソースコード上を移動して Person を定義し,また元の場所に戻ってきて続きを書くのも嫌い

関数内構造体定義はできてもいいですね。

> その構造体まるごとどこかに代入できるわけじゃないし(object型を除く)。

object に代入しても元に戻せないやね。

結局 var はシンタックスシュガーでしかないので。
関数の引数にも var 書けるようになれば別でしょうけど。

# re: 暗黙的型付け(その2) 2007/12/26 17:21 NyaRuRu

なるほど.
私は関数内型宣言が行いたいので,その「デメリット」として var を使うことにそれほどためらいはなく,
シャノンさんは関数内型宣言ができると良いかもしれないが,それはvarを使う「デメリット」の方が大きいから嫌だ,という感じでしょうか.

# re: 暗黙的型付け(その2) 2007/12/26 17:22 NyaRuRu

訂正
>それはvarを使う「デメリット」の方が大きいから嫌だ,という感じでしょうか.

現状ではvarを使う「デメリット」の方が大きいから嫌だ

# re: 暗黙的型付け(その2) 2007/12/26 17:28 NyaRuRu

> その構造体まるごとどこかに代入できるわけじゃないし(object型を除く)。

基本的に匿名型は射影操作のソースに使ってます.
あとはその匿名型を引数にとる関数をインラインで定義していくだけですかね.
http://d.hatena.ne.jp/NyaRuRu/20070623/p1

慣れるとそこまで不自由にも思わないです.

# re: 暗黙的型付け(その2) 2007/12/26 17:36 シャノン

> 関数内型宣言ができると良いかもしれないが,現状ではvarを使う「デメリット」の方が大きいから嫌だ,という感じでしょうか

そんなところです。

> http://d.hatena.ne.jp/NyaRuRu/20070623/p1

何が書いてあるんだかわかりませんでしたww

C#はともかくとして、真の動的型を持つ関数型言語なんて、俺にはとてもじゃないが脳内推論が追いつきません。
Y-CombinatorをC# 2.0で再現しようとして二晩泣いたorz

# re: 暗黙的型付け(その2) 2007/12/26 17:46 シャノン

あと、配列を書くときに、

var hoge = new { int ID; string Name; }[]
{ { 1, "ほげ" }, { 2, "はげ" }, { 3, "ひげ" } };

とか書けたら、ちょっと好感度アップでした。

# re: 暗黙的型付け(その2) 2007/12/26 17:50 NyaRuRu

ちなみに匿名型だと漏れなく参照型になるため XNA (主に Xbox 360 CLR)で死ヌってのはあります.
DLR も参照型ラヴだし,そろそろ値型スキーのための .NET 言語が欲しいかも……
って C++/CLI?

# re: 暗黙的型付け(その2) 2007/12/26 17:53 アキラ

>var hoge = new { int ID; string Name; }[]
{ { 1, "ほげ" }, { 2, "はげ" }, { 3, "ひげ" } };

これ同意です
匿名型でのオブジェクト初期化子ではプロパティに型を書けてほしかった

# re: 暗黙的型付け(その2) 2007/12/26 18:04 シャノン

> 匿名型でのオブジェクト初期化子ではプロパティに型を書けてほしかった

というかメンバ名を何度も書きたくないorz

# re: 暗黙的型付け(その2) 2007/12/26 18:10 アキラ

なるほど、つまりC++のboost::tupleですね

# 仕様は変わっても真理は変わらない 2007/12/26 20:06 菊池 Blog

仕様は変わっても真理は変わらない

# re: 暗黙的型付け(その2) 2007/12/26 20:46 アキラ

>「使えるところは使え」
>C#3.0 の言語仕様は、使うべきところで無いところは、var が使えないように設計されていると感じる


ちなみにこれは
「varと書けるとこは全部varで書く」ということですか?

# かなり批判されてますが

# VS2008が広まると理髪店が儲かる  そのわけはにっけ…(内容:varキーワードについて) 2007/12/26 20:58 "ウェブ100" は "GSP.NET GJAX!"に変わり

VS2008が広まると理髪店が儲かる  そのわけはにっけ…(内容:varキーワードについて)

# re: 暗黙的型付け(その2) 2007/12/27 9:24 じゃんぬねっと

>「使えるところは使え」

私も反対ですね。

ちなみに "単純な" 匿名型における利用であれば多くの場合許せます。
このあたりは NyaRuRu さんとシャノンさんの中間くらいの意見になるかな。
思想的にはシャノンさん寄りですが、面倒という思いも持っています。
(勝手に作ってくれるならそれでもいいけど、最近の IDE は魅せたくないコードは隠す傾向にある模様)

たぶん私の場合 '定義' をイヤがって書きます。
というかそのためのもので、セットだと思います > var

 逆 を い え ば
  そ れ 以 外 の シ ナ リ オ で 使 う 意 味 は な い

と考えています。
だから for (var i = 0;... とかはありえないです。

# re: 暗黙的型付け(その2) 2007/12/27 9:28 じゃんぬねっと

絶対的に反論が許されないのはシャノンさんが繰り返し書いているとおりです。
同じようなことを敢えて誤解を恐れまくってもっと強く口調で言うと、

「だったら優位性をいくつか挙げてみろよ。オラオラw」

です。

型を明示しているメリットはあります。
var を使う理由は先にも書いたように匿名型くらいしか私には思いつきません。

やっぱり私の勉強不足なんでしょうか?
誰かオシエテ。オシエテ。ボスケテ。

# re: 暗黙的型付け(その2) 2007/12/27 9:33 じゃんぬねっと

> 結局、var を用いる場合、用いる側(あるいは読み手)は、何に推論されるのかを知った上で書く(読む)必要があると思うのです。
> これは結果的に var を用いても常に型を意識しなければならないことに変わりは無い、と言うことを示しているのではないでしょうか。

言いたい理屈はわかるけども "無用に var を使う" 理由になる理屈でないですね。

var person = new {
  Id = 1,
  Name = "じゃんぬ",
  Age = 23
};

はいいんですけど、

for (var i = 0; i < hoge.Count; ++i)
var b = (byte)5;
var d = 4m;
var i = 5;

などで var を使う理由になりません。
たぶんここの説明がないから萌えているのだと...

# re: 暗黙的型付け(その2) 2007/12/27 11:00 Streetw☆

Σ私も議論に参加しないと...
緑文字の前後って大事だと思うんです。
そこでverってw。今回の主役なのに><
なぜかビャーって読みましたw

# re: 暗黙的型付け(その2) 2007/12/27 11:57 NyaRuRu

>boost::tuple

シャノンさん的には
tuple<int, string, int> t1 = make_tuple(1, string("じゃんぬ"), 23);
と書く人は好感度ダウンで,

tuple<int, string, int> t2 = make_tuple<int, string, int>(1, "じゃんぬ", 23);
と書くと好感度アップな気がしますね.なんとなく.

# re: 暗黙的型付け(その2) 2007/12/27 12:09 アキラ

これは

>tuple<int, string, int> t1 = make_tuple(1, string("じゃんぬ"), 23);

こう書けますけどね
tuple<int, string, int> t1 = make_tuple(1, "じゃんぬ", 23);

ぼくはこっちがシャノンさんフラグが立つ方だと思いますw

# re: 暗黙的型付け(その2) 2007/12/27 12:45 NyaRuRu

>シャノンさんフラグ

確かに.
てか,これもいけるのかー.びっくり.へーへー
tuple<float, int> a = std::make_pair(1, 'a');

# 型推論とは、人間には明らかに分かる型に対して、いちいち型名を明示しない事 2007/12/27 13:05 囚人のジレンマな日々

型推論とは、人間には明らかに分かる型に対して、いちいち型名を明示しない事

# 暗黙的型付け(その3) 2007/12/27 14:25 R.Tanaka.Ichiro's Blog

暗黙的型付け(その3)

# 暗黙的型付け(その3) 2007/12/27 14:32 R.Tanaka.Ichiro's Blog

暗黙的型付け(その3)

# re: 暗黙的型付け(その2) 2007/12/27 14:46 R・田中一郎

おかしいなぁ、Streetw☆ さんは必ず反応してくれるネタだと思っていたんですが^^;

唯一反応していただいたのは、ビャーだけだったとは(>_<)

# re: 暗黙的型付け(その2) 2007/12/27 15:12 シャノン

boostはよく知らんのだけれど、関数テンプレートの型推論は違和感ないですねぇ。…矛盾してる?
フラグとか言うと、まるでギャルゲでアキラさんルートに入ったみたいに聞こえるのでやめていただきたいw

# re: 暗黙的型付け(その2) 2007/12/27 15:27 Streetw☆

がっくりさせちゃったみたいなのでw、その1の時に書いてお蔵入りにしてたのを投稿します。
決め手に欠けるのでコメントしませんでした。

私が絶対使うところ。
・LINQの結果
・匿名型のところ
・StringBuilder sb = new StringBuilder();みたいなとこ
前にもどこかで書いたけど、3つめは一度普通に書いてから、左辺のStringBuilderを消してvarに変更しますw

そして、使わないところですけど、人が推論しづらいところは使わない方がいいかもって思ってます。

具体例です。
for (var i = 0; i < count; i++);
…ダメと言う人が多いと思うけど、人も推論は簡単なのでいいかな。
 私はたぶん使わないけどw
var age = persion.Age
…十中八九、intなのでいいかもw
var value = GetValue();
…ここを見ただけでは人が推論できないから良くないと思います。
var itemCode = target.ItemCode;
…そのプロジェクトとしては当たり前なことでしたらいいかも。

既出な話があったらごめんなさい。

# re: 暗黙的型付け(その2) 2007/12/27 16:38 じゃんぬねっと

シャノンさんフラグ、ワロスwwww

数値だけ扱う前提なら型は意識しなくていい世の中になっているので、メソッドで直接利用するのはおkという見方もありますね。
ただ変数に格納するなら明示しておいてもいいんじゃないかなと思います。

仕様変更をどう考えるかにも因りますけど。

# re: 暗黙的型付け(その2) 2007/12/27 16:55 R・田中一郎

シャノン さん

>boostはよく知らんのだけれど、関数テンプレートの型推論は違和感ないですねぇ。…矛盾してる?

この違和感というのが実は真理のような気がするんですよね。

---------------------------------------------------------
Streetw☆ さん

>前にもどこかで書いたけど、3つめは一度普通に書いてから、左辺のStringBuilderを消してvarに変更しますw

僕と一緒ですね^^;

>そして、使わないところですけど、人が推論しづらいところは使わない方がいいかもって思ってます。

うーん、やっぱり人それぞれで意見が変わるんですね。
後数年すると、答えが見えてくるのかなー、なんて気がしてきました。
で、その頃になって、ここを読み直すと恥ずかしい気持ちになったりするのかなー

---------------------------------------------------------
じゃんぬねっと さん

>仕様変更をどう考えるかにも因りますけど。

遠い昔に、列挙型の値に、列挙した文字列と同じ値を格納したいと考えたことがありました。
その時、じゃんぬねっとさんがリフレクションを使ったサンプルを提示して下さいましたっけ。

それに近いものがありますかね。

根本的には、一か所いじれば皆変わるー、という書き方が好きなんですよね・・・
まあ、実現できない場合が多いのですけれども。

# re: 暗黙的型付け(その2) 2007/12/27 17:33 じゃんぬねっと

> それに近いものがありますかね。

私が受ける印象とはちょっと違いますね。
あのサンプルだと型も中身もあれで自明ですし単に手間だったからというのが理由になります。
var で問題にしている事情とは違います。

> 根本的には、一か所いじれば皆変わるー、という書き方が好きなんですよね・・・
> まあ、実現できない場合が多いのですけれども。

そのあたりは IDE にやらせたいと思っています。
あくまでソースは明示で、作業は単純でが至高だと考えています。

# varは、2007年のクリスマスプレゼント? 2007/12/28 9:39 石野光仁 Blog

varは、2007年のクリスマスプレゼント?

# re: 暗黙的型付け(その2) 2007/12/28 9:59 R・田中一郎

じゃんぬねっと さん

>var で問題にしている事情とは違います。

確かに一致しているのは var は何かに依存するという点でのみですからね。

>そのあたりは IDE にやらせたいと思っています。

僕としては、この辺りは、あまり拘りはありません。

>あくまでソースは明示で、作業は単純でが至高だと考えています。

このための方法論というお話ですよね?^^;

# 仕様は変わっても真理は変わらない 2007/12/28 11:57 菊池 Blog

仕様は変わっても真理は変わらない

# 暗黙的型付け(その4) 2007/12/28 13:34 R.Tanaka.Ichiro's Blog

暗黙的型付け(その4)

# 4 One of the I would want 1 2020/01/01 6:41 Typicalcat71

http://bktmedia.in/%ef%bb%bfseniors-dating-online-service-for-relationships-full-free/ no fee newest seniors dating online sites http://jackierupp.com/no-subscription-newest-mature-dating-online-website-blogs.wankuma.com.pdf dallas black mature dating online website

タイトル  
名前  
Url
コメント