繁体   English   中英

为什么不能在 static 方法中访问我声明的非 static 字段?

[英]Why can't my declared non static field be accessed inside static method?

嗨,我是 C# 的新手,我从表面上知道我不能在 static 方法中使用非 static 字段。 但是我有一种情况,我想从概念上理解。

看看这个代码片段:

class CIMConversionHelper
{
    private static Logger Logger = LogManager.GetCurrentClassLogger();
    private readonly ProcessingEndTimeData _procEndTimeData = new ProcessingEndTimeData();

    public static TDX2KlarfResult HandleConversion(TDXProcessItem item, string fileName)
    {

        TDX2KlarfResult result = new TDX2KlarfResult();
        result.success = true;
        
        XmlDocument doc = new XmlDocument();
        try
        {
            doc.Load(fileName);
        }
        catch (Exception ex)
        {
    
            result.success = false;
            Logger.Error(ex, "XML Parsing Error: ");
            return result;
        }
        

        _procEndTimeData.ToolType = toolType;
        _procEndTimeData.Lot = input.cimToolContext.LOT;
        _procEndTimeData.WaferScribe = input.cimWaferContainer.waferContext.WAFER_SCRIBE;
        _procEndTimeData.Processing_End_Time = input.cimToolContext.PROCESSING_END_TIME;
        
    }

    public static TDX2KlarfResult Convert(TDXProcessItem item, string fileName)
    {

        TDX2KlarfResult result = new TDX2KlarfResult();
        result.success = true;
        try
        {
            result = CIMConversionHelper.HandleConversion(item, fileName);
        }
        catch (Exception ex)
        {
            // Failed to Parse the xml Not good mark nonrecoverable error and return.
            result.errorType = "Non-Recoverable";
            result.success = false;
            Logger.Error(ex, "Unknown Error: ");
            return result;
        }
        if (result.success)
        {
            //DBHelper.AddProcessingEndTimeToDB();
        }
        return result;
    }

}

这是一个非常精简的片段,但它抓住了我的问题。 我创建了一个 object 引用作为名为 _procEndTimeData 的 ProcessingEndTimeData 字段。

为什么它在 Visual Studio 中告诉我:“非静态字段、方法或属性 CIMConversionHelper._procEndTimeData 需要 object 引用?

我想我应该能够在 static function “HandleConversion” 的第 4 行中为声明的 object “_procEndTimeData” 赋值

有人可以向我解释为什么这个参考是不够的吗? 以及为什么我必须在 static function HandleCOnversion 中创建另一个 ProcessingEndTimeData object?

我知道我可以将 _procEndTimeData 切换为 static 但如果我已经在字段级别创建了引用,为什么还需要这样做?

想想设备的memory。

当你创建一个 object 时,memory 是为它保留的。 想象一下,由于其属性(int、char...),它占用 32 个字节。 如果您创建 10 个对象,您将在 memory 中为您的对象占用 320 个字节。

但是当您使用“静态”时,这些属性只会为 class 创建一次。您创建的每个 object 都不会创建一次。

因此,您的 10 个对象可以访问它们自己的属性(int、char...)以及 static 的属性。 但是从“静态”方法中,您无法访问该 class 的 object 的属性,因为您没有它的实例。

一个非常简单的示例:您有一个具有 Name 属性的用户 class。 您添加一个类型为 integer 的 static 变量:static int 计数。 该变量将用于记录您创建的用户数。 在用户的构造函数中,您可以执行 count++,因为 class 的实例可以访问 class 的属性。但是如果您创建一个 static 方法:

public static void DoSomething()
{
   // You can show a message with the number of users
    MessageBox.Show(count.ToString());

   // But you CAN'T access to a "Name" because this method is not 
   // a method of one concrete user. It's a general method, for all users
}

如果您调用 DoSomething 并且创建了两个用户“Tom”和“Jerry”,在 DoSomething 中您不知道任何用户。

您有 2 个选择来完成这项工作。 不确定哪一个适用。 我的猜测是我将展示的第一个

  private readonly ProcessingEndTimeData _procEndTimeData = new ProcessingEndTimeData();

改成

  static private readonly ProcessingEndTimeData _procEndTimeData = new ProcessingEndTimeData();

这表示该字段也是 static,即属于 class,而不属于 CIMConversionHelper class 的实例。

替代方案,我认为您不希望它在该方法中创建 CIMConversionHelper 的实例。 正如我所说,这可能不是您想要的。

如果您的意图是此 class (CIMConversionHelper) 全部为 static,即您永远不会创建它的实例,则将 class 本身标记为 static,编译器将确保您不会意外创建非 static 成员。 IE

static class CIMConversionHelper{....}

为什么会这样?

你说你在这里创建了一个引用

 private readonly ProcessingEndTimeData _procEndTimeData = new ProcessingEndTimeData();

你还没有创造它。

您需要了解 static 与实例函数和字段之间的区别。

让我们举个例子。 我们有一个 class Thingy。 它包括一个工厂方法,该方法可以生成事物实例记录它生成的数量

 public class Thingy{
     static s_thingyCount = 0;
     string _froop;
     public static CreateThingy(){
           var thing = new Thingy();
           ......
           s_thingyCount++;
           thing._froop  = "hello";
           return thing;
     }

     public void Twang(int froop){
        ......
     }
     public int Oink(string pling){
        ......
        _froop = pling;
     }

  }

我们可以 go

   var t1 = Thingy.CreateThingy();
   t1.Oink("Ole");

CreateThingy 不对 class 的实例进行操作,它对 class 本身进行操作。 count变量不属于一个实例,它属于class本身。 请注意,在创建方法中我们必须说

    thing._froop  = "hello";

即我们要设置哪些对象_froop(我们正在制作的对象)。

    var t1 = Thingy.CreateThingy();          

现在我们有了一个 Thingy 的实例,我们可以在它上面调用方法

     t1.Oink("Ole");

看那个方法

     public int Oink(string pling){
        ......
        _froop = pling;
     }

我们不说要设置哪个froop,我们正在操作 class 的一个实例。

我们做不到

     Thingy.Oink("xxx");

哪个 THingy 会更新? 我们也做不到

     Thingy._froop = "fff";

出于同样的原因

但我们可以做到

     var count = Thingy.s_thingyCount;

这个map是怎么变成你的class的。这个方法是static。它就像CreateThingy,它没有实例可以操作。

 public static TDX2KlarfResult HandleConversion(TDXProcessItem item, string fileName)

但你这样做

  _procEndTimeData.ToolType = toolType;

有了这个领域

 private readonly ProcessingEndTimeData _procEndTimeData = new ProcessingEndTimeData();

这就像做

   _froop = "hello"

在 CreateThingy

_proceEndTimeData 仅存在于您的 class 上的实例中。

它将在您创建时创建

     new CIMConversionHelper();

但我怀疑那不是你想要做的。 所以你需要使_proceEndTimeData static,就像s_thingyCount

如果我理解正确,你回答自己:“我知道在表面上我不能在 static 方法中使用非 static 字段”,然后你在你的方法中声明了一个非 static 变量:

私有只读 ProcessingEndTimeData _procEndTimeData

它应该是 static,如果你愿意,除了只读。

其原因与面向 object 的编程有关。 要从 class 访问 static 方法,您不需要实例化它。 这就是为什么您不能在 class 的 static 方法中引用类级非 static 变量的原因。希望这能让它更清楚一点。

我知道我可以将 _procEndTimeData 切换为 static 但如果我已经在字段级别创建了引用,为什么还需要这样做?

你没有创建这样的东西,你的_procEndTimeDataCIMConversionHelper的每个实例中的一个字段,你没有。

如果它能帮助您更好地想象问题,想象一下如果您的期望是现实并且您有以下代码会发生什么:

CIMConversionHelper h1 = new(), h2 = new();
CIMConversionHelper.Convert(.....whatever....);

它会改变h1._procEndTimeData吗? h2._procEndTimeData 它必须选择一个,对吗? 那么它会选择哪一个呢?

static号方法只能使用static字段,句号。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM