Home > Back-end >  Why can't my declared non static field be accessed inside static method?
Why can't my declared non static field be accessed inside static method?

Time:03-18

Hi I am new to C# and I am aware on a surface level that I cannot use non static fields inside static methods. But I have a situation that I am trying to understand conceptually.

Check out this code snippet:

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

}

This is a very abridged snippet but one that captures my question. I have created an object reference as field for ProcessingEndTimeData called _procEndTimeData.

Why then is it telling me in Visual Studio that: "an object reference is required for the non-static field, method, or property CIMConversionHelper._procEndTimeData?

I thought I should be able to assign values to the declared object "_procEndTimeData" in the 4th line inside the static function "HandleConversion"

Can someone explain to me why this reference is not enough? and why I would then have to create yet another ProcessingEndTimeData object inside the static function HandleCOnversion?

I know I can just toggle _procEndTimeData to be static but why do I need to do this if I have already created a reference in the field level?

CodePudding user response:

Think about the memory of the equipment.

When you create an object, memory is reserved for it. Imagine, that because of its properties (int, char...) it occupies 32 bytes. If you create 10 objects, you will have 320 bytes occupied in memory for your objects.

But when you use "static", those properties are created only once for the class. Not once for each object you create.

So, your 10 objects can access their own properties (int, char...) and also the static ones. But from a "static" method you cannot access the properties of an object of that class because you don't have the instance of it.

A very simple example: You have a User class with the Name property. You add a static variable of type integer: static int count. That variable will be used to record the number of users you create. In the constructor of the user you can do count because the instances of the class can access to the properties of the class. But if you create a static method:

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
}

If you invoke DoSomething and you are created two users, "Tom" and "Jerry", in DoSomething you don't know any user.

CodePudding user response:

If I'm understanding it correctly, you answered yourself: "I am aware on a surface level that I cannot use non static fields inside static methods", and then you have declared a non static variable inside your method:

private readonly ProcessingEndTimeData _procEndTimeData

It should be static, apart than readonly if you want.

The reason for this has to do with object oriented programming. To access a static method from a class you don't need to instantiate it. This is why you can't reference class-level non static variables inside a static method from that class. Hope that made it a little clearer.

CodePudding user response:

I know I can just toggle _procEndTimeData to be static but why do I need to do this if I have already created a reference in the field level?

You created no such thing, your _procEndTimeData is a field in every instance of CIMConversionHelper, of which you have none.

If it helps you visualize the problem better, imagine what would happen if your expectation was reality and you had the following code:

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

Would it change h1._procEndTimeData? h2._procEndTimeData? It has to pick one, right? So which one does it pick?

No. static methods can only use static fields, period.

CodePudding user response:

You have 2 choices to make this work. Not sure which one applies. My guess is the first one I will show

  private readonly ProcessingEndTimeData _procEndTimeData = new ProcessingEndTimeData();

change to

  static private readonly ProcessingEndTimeData _procEndTimeData = new ProcessingEndTimeData();

This says that this field is also static, ie belongs to the class, not to instances of the CIMConversionHelper class.

The alternative, which I dont think you want it to create an instance of CIMConversionHelper in that method. Which as I said is probably not what you want.

If your intent is that this class (CIMConversionHelper) is all static, ie you will never create an instance of it then mark the class itself static and the compiler will ensure that you dont accidentally create non static members. ie

static class CIMConversionHelper{....}

Why is this so?

You say you have created a reference here

 private readonly ProcessingEndTimeData _procEndTimeData = new ProcessingEndTimeData();

YOu have not created it yet.

You need to understand the difference between static and instance functions and fields.

Lets have an example. We have a class Thingy. It includes a factory method that makes thingy instances and keeps a count of how many it has made

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

  }

we can go

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

The CreateThingy does not operate on instances of the class, it operates on the class itself. The count variable does not belong to an instance, it belongs to the class itself. Note that in the create method we have to say

    thing._froop  = "hello";

ie which objects _froop we want to set (the one we are in the process of making).

    var t1 = Thingy.CreateThingy();          

now we have an instance of Thingy we can call methods on it

     t1.Oink("Ole");

Look in that method

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

we dont say which froop to set, we are manipulating an instance of the class.

We cannot do

     Thingy.Oink("xxx");

Which THingy would be updates? Nor can we do

     Thingy._froop = "fff";

for the same reason

but we can do

     var count = Thingy.s_thingyCount;

How does this map to your class. THis method is static. It is like CreateThingy, it does not have an instance to operate on.

 public static TDX2KlarfResult HandleConversion(TDXProcessItem item, string fileName)

but you do this

  _procEndTimeData.ToolType = toolType;

with this field

 private readonly ProcessingEndTimeData _procEndTimeData = new ProcessingEndTimeData();

this is just like doing

   _froop = "hello"

in CreateThingy

_proceEndTimeData only exists in instances on your class.

It will be create when you do

     new CIMConversionHelper();

But I suspect thats not what youo want to do. So you need to make _proceEndTimeData static, just like s_thingyCount

  •  Tags:  
  • c#
  • Related