关键是要加一个类型参数:
abstract class Base<T>
where T : Base<T>
{
public static string GetClassName()
{
return typeof(T).Name;
}
}
class A : Base<A> { }
class B : Base<B> { }
这使得Base 的静态成员属于特定类Base<T>,无论T 是什么。所以不再有单一的Base.GetClassName 方法,但在这种情况下,现在有两种方法:Base<A>.GetClassName 和Base<B>.GetClassName。此外,类型参数的约束使得不可能有class B : Base<A>,这保证了A.GetClassName 和B.GetClassName 将返回不同的东西。
特定于子类的行为可以进一步扩展:
abstract class Base<T>
where T : Base<T>
{
private static HashSet<string> values = new HashSet<string>();
internal Base(string value)
{
if (Base<T>.values.Contains(value))
throw new Exception("Not unique");
else
Base<T>.values.Add(value);
}
public static string GetClassName()
{
return typeof(T).Name;
}
public static IEnumerable<string> GetValues()
{
return new LinkedList<string>(Base<T>.values);
}
}
class A : Base<A>
{
public A(string value) : base(value) { }
}
class B : Base<B>
{
public B(string value) : base(value) { }
}
static void Main(string[] args)
{
var a1 = new A("value");
var a2 = new A("value 2");
// var a3 = new A("value"); // Would throw an exception
var b = new B("value"); // Does not throw an exception
Console.WriteLine(A.GetClassName()); // Prints "A"
Console.WriteLine(B.GetClassName()); // Prints "B"
Console.WriteLine("The values in A:");
foreach (var value in A.GetValues()) // This loop prints "value" and "value 2"
{
Console.WriteLine("\t" + value);
}
Console.WriteLine("The values in B:");
foreach (var value in B.GetValues()) // This loop prints "value"
{
Console.WriteLine("\t" + value);
}
}
在这种情况下,Base<A>/A 和 Base<B>/B 中有不同的静态 values 对象。
然而,所有这些都是有代价的。在上面的示例中,Base 的子类不可能在所有子类先验相互了解的情况下访问相同的静态对象。例如。 B 无法访问与 A 相同的 values 对象。当您希望所有子类共享值时,一种可能的解决方法是使用Base<agreed-upon-type>.values。