如何使静态方法的行为依赖于它调用的类? E.g。
abstract class Base
{
public static string GetClassName()
{ ???? }
}
class A : Base { }
class B : Base { }
static void Main(string[] args)
{
Console.WriteLine(A.GetClassName()); // Want to print "A"
Console.WriteLine(B.GetClassName()); // Want to print "B"
}
请注意,如果我在MethodBase.GetCurrentMethod().DeclaringType.Name
中使用Base.GetClassName
,则会返回“Base”。
另请注意,这与其他几个SO问题类似,如下所示,但我要以更简洁的方式询问它,以便记录除“你不能”之外的答案:
答案 0 :(得分:0)
关键是要添加一个类型参数:
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
。此外,对type参数的约束使得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);
}
}
在这种情况下,values
/ Base<A>
和A
/ Base<B>
中有不同的静态B
对象。
然而,所有这些都需要付出代价。在上面的例子中,Base
的子类不可能访问相同的静态对象而没有所有子类知道彼此先验。例如。 B
无法访问与values
相同的A
对象。一种可能的解决方法是在希望所有子类共享值时使用Base<agreed-upon-type>.values
。