C#:基类可以在静态函数中使用派生类的变量吗?

时间:2009-04-05 05:05:36

标签: c#

有没有让基类在C#中使用派生类的静态变量?像这样:

class Program
{
    static void Main(string[] args)
    {
        int Result = DerivedClass.DoubleNumber();
        Console.WriteLine(Result.ToString());   // Returns 0
    }
}

class BaseClass
{
    public static int MyNumber;

    public static int DoubleNumber()
    {
        return (MyNumber*2);
    }
}

class DerivedClass : BaseClass
{
    public new static int MyNumber = 5;
}

我试图让它返回10,但我得到0。

这里是我使用它的地方:我有一个名为ProfilePictures的类,它带有一个名为GetTempSavePath的静态函数,它将用户id作为参数,并返回临时文件的物理路径。路径库是一个名为TempPath的静态变量。由于我在多个项目中使用此类并且它们具有不同的TempPath,因此我创建了一个派生类,将该变量设置为项目的路径。

另请参阅

  

Why can’t I declare C# methods virtual and static?

6 个答案:

答案 0 :(得分:6)

除了已经指出的事实......静态变量被绑定或绑定到声明它们的特定类,并且不能被覆盖。覆盖/多态性需要实例才能工作。

您的问题可以通过改变设计来解决。

string ProfilePictures.GetTempSavePath(SomeType UserId, string sBasePath)

如果只需要这2个变量来计算返回值,则可以将其保留为实用程序/静态方法。现在,您可以提供不同的基本路径..

现在看来,您需要在多个项目(具有固定基本路径)中使用此类,并对基本路径进行硬编码,这样您就不必为每个调用指定它。 类型/类层次结构应基于行为定义,而不是基于数据。变量可以处理数据的变化。因此我建议将basepath值保存为静态成员变量,该变量是从资源文件初始化的(DoubleClick项目属性节点>设置>添加新设置文件>添加新的设置名为BasePath - string - 应用程序范围 - VALUE = C:\Users)。现在你只需要为每个项目调整app.config文件,不需要更改代码,不需要硬编码,也不需要多种类型。

public class PathHelper
{
  static string _sBasePath;
  static PathHelper()
  {
     _sBasePath = Properties.Settings.Default.BasePath;
  }

  static string GetTempSavePath(string sUserId)
  {
     // dummy logic to compute return value, replace to taste
     return Path.Combine(_sBasePath, sUserId.Substring(0, 4));
  }
}

希望有意义

答案 1 :(得分:2)

问题在于您在派生类中重新声明静态变量。 DerivedClass中的MyNumber声明隐藏了基类中的声明。如果删除该声明,则派生类静态函数中对“MyNumber”的引用将引用基类变量。当然,如果删除声明,则无法在派生类中使用静态初始值设定项。

您可能需要考虑要求用户实例化ProfilePictures的实例,而不是为GetTempSavePath提供静态函数。这样,您可以覆盖GetTempSavePath方法以提供正确的TempPath。或者,您可以在派生类构造函数中设置静态路径值的值。

尽管可以将继承与静态成员一起使用,但如果没有“this”指针,则不能依赖于多态行为。

答案 2 :(得分:1)

静态成员不是虚拟成员,因此您无法覆盖它们。

当您致电DerivedClass.DoubleNumber时,您实际上正在调用BaseClass.DoubleNumber,因为DerivedClass类没有该方法。此外,无论您如何调用该方法,该方法中MyNumber的使用始终为BaseClass.MyNumber

您要查找的是可以在派生类中覆盖的虚拟属性。由于虚拟成员不能是静态成员,因此您需要使用该类的实例。如果保持对实例的引用是不切实际的,则可以使用单例模式。

答案 3 :(得分:1)

这种方式有效:

public class ClassA
{
    protected static int num = 5;

    public static int GetNum()
    {
        return num;
    }
}

public class ClassB : ClassA
{
    static ClassB()
    {
        num = 6;
    }
}

但是,请注意在实例化一个对象之前和之后调用ClassB.GetNum()时的区别。静态初始化程序在您创建至少一个之前不会运行,因此如果没有创建任何内容,您将获得5,如果至少有一个对象,则为6。

答案 4 :(得分:0)

提供一个返回静态类的虚方法。

class BaseClass
{
    public virtual int GetMyNumber() { return MyNumber; }
}

您可能想要使用虚拟财产......

答案 5 :(得分:0)

如果要封装整个对象的逻辑,也不建议使用过多的静态成员。例如,您的代码可以通过以下方式正确重写...这是oops中最推荐的,

class Program
{
    static void Main(string[] args)
    {
        int Result = DerivedClass.Instance.DoubleNumber();
        Console.WriteLine(Result.ToString());   // Returns 0
    }
}

class BaseClass
{
    protected BaseClass(){} // this enforces that it can not be created

    public int MyNumber;

    public virtual int DoubleNumber()
    {
        return (MyNumber*2);
    }
}

public class DerivedClass : BaseClass
{
    // this also ensures that it can not be created outside
    protected DerivedClass(){
        MyNumber = 5;
    }

    // only way to access this is by Instance member...
    public static DerivedClass Instance = new DerivedClass();
}

这是我们访问.Net Library提供的配置值和许多其他单实例静态对象的方法。