C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: new修飾子による隠蔽とジェネリクス


(過去ログ 53 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■29783 / inTopicNo.1)  new修飾子による隠蔽とジェネリクス
  
□投稿者/ KAZUu (4回)-(2008/12/14(Sun) 20:11:36)

分類:[C#] 

C# 2.0 以降の話題です。

泥爺氏のブログの記事を読んでいて疑問に感じたのですが、
http://daisy64.blogspot.com/2008/08/generic.html

以下のようなコードを実行した際に、

class Super
{
	public void Write()
	{
		Console.WriteLine("Super");
	}
}
class Sub : Super
{
	public new void Write()
	{
		Console.WriteLine("Sub");
	}
}
class Program
{
	static void Main(string[] args)
	{
		Hoge(new Sub());
	}
	public static void Hoge<T>(T t) where T : Super
	{
		Console.WriteLine(typeof(T).Name);
		t.Write();
	}
}

どういう理屈で、
Sub
Super
と実行されるのでしょうか?

引用返信 編集キー/
■29785 / inTopicNo.2)  Re[1]: new修飾子による隠蔽とジェネリクス
□投稿者/ Hongliang (322回)-(2008/12/14(Sun) 21:43:31)
T は Super で制約されるので、Super として扱われます。
引用返信 編集キー/
■29786 / inTopicNo.3)  Re[2]: new修飾子による隠蔽とジェネリクス
□投稿者/ 囚人 (309回)-(2008/12/14(Sun) 21:46:48)
単に
Super s1 = new Sub();
としたときと同じ扱いになるだけですね。

引用返信 編集キー/
■29788 / inTopicNo.4)  Re[1]: new修飾子による隠蔽とジェネリクス
□投稿者/ よねKEN (233回)-(2008/12/14(Sun) 21:54:49)
> どういう理屈で、
> Sub
> Super
> と実行されるのでしょうか?

厳密な説明になっていないと思いますが、だいたい以下のような感じです。

> 		Console.WriteLine(typeof(T).Name);

このTはILコードにコンパイルされた段階では、SuperまたはSuperの派生クラスの
何かということしか明示されていません。型Tが決定されるまで結果は不明です。

> 		t.Write();

こちらのtはSuperまたはSuperの派生クラスのインスタンスであることがコンパイル時に
わかっているので、SuperのWrite仮想メソッドを呼び出すようにコンパイルされます。
(Sub.WriteはSuper.Writeとたまたま同じ名前というだけで、Super.Writeとは無関係なメソッド
 であると理解するとわかりやすいかと思います。)


引用返信 編集キー/
■29811 / inTopicNo.5)  Re[2]: new修飾子による隠蔽とジェネリクス
□投稿者/ KAZUu (5回)-(2008/12/15(Mon) 13:02:59)
>> Console.WriteLine(typeof(T).Name);
>
> このTはILコードにコンパイルされた段階では、SuperまたはSuperの派生クラスの
> 何かということしか明示されていません。型Tが決定されるまで結果は不明です。
>
>> t.Write();
>
> こちらのtはSuperまたはSuperの派生クラスのインスタンスであることがコンパイル時に
> わかっているので、SuperのWrite仮想メソッドを呼び出すようにコンパイルされます。
> (Sub.WriteはSuper.Writeとたまたま同じ名前というだけで、Super.Writeとは無関係なメソッド
> であると理解するとわかりやすいかと思います。)

なるほど、ILコードを生成する時点では総称型TをSuper型として扱い、
tの静的な型はSuper型であるとしてコンパイルされるという考えた方でよろしいのでしょうか?

C++のtemplateのように、コンパイル時に総称型TはSub型であると分かるはずなのに、
なぜ、tの静的な型をSub型として扱ってくれないのかと納得できず質問しました。
ジェネリクスはただの置換ではないのですね。

Hongliangさん、囚人さん、よねKENさん、どうもありがとうございました。

解決済み
引用返信 編集キー/
■29837 / inTopicNo.6)  Re[3]: new修飾子による隠蔽とジェネリクス
□投稿者/ aetos (45回)-(2008/12/15(Mon) 17:50:41)
No29811 (KAZUu さん) に返信
> C++のtemplateのように、コンパイル時に総称型TはSub型であると分かるはずなのに、
> なぜ、tの静的な型をSub型として扱ってくれないのかと納得できず質問しました。
> ジェネリクスはただの置換ではないのですね。

そうです。
コンパイル時に T の型が分かるのは、総称型/総称メソッドと、それを利用するコードを一緒にコンパイルする場合だけです。
.NET Framework では、例えば List<T> が mscorlib.dll によって公開されており、そのソースコードがないにもかかわらず、List<MyType> がコンパイル可能です。
引用返信 編集キー/
■30044 / inTopicNo.7)  Re[4]: new修飾子による隠蔽とジェネリクス
□投稿者/ KAZUu (6回)-(2008/12/17(Wed) 16:39:36)
> そうです。
> コンパイル時に T の型が分かるのは、総称型/総称メソッドと、それを利用するコードを一緒にコンパイルする場合だけです。
> .NET Framework では、例えば List<T> が mscorlib.dll によって公開されており、そのソースコードがないにもかかわらず、List<MyType> がコンパイル可能です。

なるほど。
総称型を含むアセンブリとそれを利用するアセンブリをコンパイルして実行する際に、具体的な型が決定されると。
一方、 t.Write(); はアセンブリが生成された時点で、呼び出すメソッドが決定されているのですね。
aetosさん、ありがとうございました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -