コンテンツへスキップ

C#のgenericsでは型パラメータを持つ型パラメータを制約するには余分な型パラメータが増えて困るorz

C#のgenericsでは、型パラメーターを持つ型パラメーターを制約するには余分な型パラメーターを増やすしかありません(私が知らないだけかもしれないです)。 これが非常に不便で、genericsを駆使して抽象化を行ってゆくと、この制約に泣かされることになります。 何のことか分からないですね。とりあえず、次のプログラムを見てください。

たとえば、次のプログラムでは、クラスFooに2つの型パラメーターにCarとPersonを代入して変数tFooを宣言してます。 第2型パラメーターのPersonを指定することが、情報量的にムダです。 なぜならば、第1型パラメーター「Car;」とクラスFooの1つ目のwhere句の右辺「Car<_Owner>;」をユニファイ(パターンマッチ)すれば、_OwnerにPersonが代入されていることは推論できるからです。

namespace MyApplication
{
	public interface Person
	{
		string Name { get; }
	}
	public interface Car<_Owner>
	where _Owner : Person
	{
		string Name { get; }
		_Owner Owner { get; }
	}
	public interface Foo<_Car, _Owner>
	where _Car : Car<_Owner>
	where _Owner : Person { }
	public class Program
	{
		public static void Main()
		{
			Foo, Person> tFoo = ...;
		}
	}
}

ローカル型変数の定義とそれを使ったユニフィケーションをC#のgenericsに導入するだけで実現できるのに、このような機能がないなんて不思議です。 もし、このような機能があれば上記のプログラムは次のようになります。変数宣言が簡潔になり、うれしいです。

namespace MyApplication
{
	public interface Person
	{
		string Name { get; }
	}
	public interface Car<_Owner>
	where _Owner : Person
	{
		string Name { get; }
		_Owner Owner { get; }
	}
	public interface Foo<_Car> local _Owner
	where _Car : Car<_Owner>
	where _Owner : Person { }
	public class Program
	{
		public static void Main()
		{
			Foo> tFoo = ...;
		}
	}
}

ユニファイによる推論がない言語では、型パラメーターの代入によって作れらる木(Foo;, Person>;など)の部分木(Car;やPersonなど)を制約しようとすると、部分木を指定するための型パラメーターを増やさなければなりません。 genericsを駆使してさまざまな型を交換可能にしたライブラリを作ろうとすると、このような問題に悩まされます。 そもそも、交換可能な部分が多いとC#のgenericsでは型パラメーターが増えまくって大変です。そういうことをやるなら、gbetaなどのファミリーポルモルフィズムが使える言語がいいですね。

© 2003 Kurusugawa Computer Inc.