【问题标题】:Static method dependent on child class?依赖子类的静态方法?
【发布时间】:2016-07-11 07:00:13
【问题描述】:

如何使静态方法的行为依赖于调用它的类? 例如

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"
}

请注意,如果我在Base.GetClassName 中使用MethodBase.GetCurrentMethod().DeclaringType.Name,则返回“Base”。

另请注意,这类似于其他几个 SO 问题,如下所示,但我以更简洁的方式提出问题,以便记录除“你不能”之外的答案:

【问题讨论】:

标签: c# abstract-class


【解决方案1】:

关键是要加一个类型参数:

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&lt;T&gt;,无论T 是什么。所以不再有单一的Base.GetClassName 方法,但在这种情况下,现在有两种方法:Base&lt;A&gt;.GetClassNameBase&lt;B&gt;.GetClassName。此外,类型参数的约束使得不可能有class B : Base&lt;A&gt;,这保证了A.GetClassNameB.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&lt;A&gt;/ABase&lt;B&gt;/B 中有不同的静态 values 对象。

然而,所有这些都是有代价的。在上面的示例中,Base 的子类不可能在所有子类先验相互了解的情况下访问相同的静态对象。例如。 B 无法访问与 A 相同的 values 对象。当您希望所有子类共享值时,一种可能的解决方法是使用Base&lt;agreed-upon-type&gt;.values

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 2022-10-19
    • 1970-01-01
    相关资源
    最近更新 更多