關鍵是要增加一個類型參數:
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<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
。
[C#虛擬(或抽象)靜態方法]的可能重複(http://stackoverflow.com/questions/763344/c-sharp-virtual-or-abstract-static-methods) –
@JasonWatkins。感謝標記爲dup。每個http://meta.stackoverflow.com/questions/314210/should-i-ask-a-new-question-in-order-to-make-the-answer-easier-to-find我應該做到這一點 –