1

i'm working with PHP code and i have not much experienced with C#, i modified my code a lot, but still experiencing error "A field initializer cannot reference the non-static field, method, or property" at line number 34 Why it happens always and how to fix it?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Finisar.SQLite;

namespace Stemmer
{
    class ValueObj
    {
        public void postfix(string table)
        {
            SQLiteConnection sqlite_conn;
            SQLiteCommand sqlite_cmd;
            SQLiteDataReader sqlite_datareader;

            sqlite_conn = new SQLiteConnection("Data Source=database.db;Version=3;New=False;Compress=True;");
            sqlite_conn.Open();
            sqlite_cmd = sqlite_conn.CreateCommand();

            sqlite_cmd.CommandText = "SELECT * FROM " + table;
            sqlite_datareader = sqlite_cmd.ExecuteReader();

            List<string> list = new List<string>();

            while (sqlite_datareader.Read())
            {
                list.Add(sqlite_datareader.GetString(1));
            }

            return list.ToArray(); // returns void, a return keyword must not be followed by an object expression

        }

        public string[] postfixList = postfix("postfixList"); // A field initializer cannot reference the non-static field, method, or property

    }
}
Ahmed iqbal
  • 597
  • 1
  • 8
  • 26

4 Answers4

3

Create a constructor and assign the field there:

public string[] postfixList;

public ValueObj()
{
  postfixList = postfix("postfixList");
}

And the returntype of postfix method must be string[] and not void

The field postfixList is an instance member of the class and is not static. The call to postfix() is outside a method and so is static. If you call it within the constructor, it is called each time when the class is instantiated.

For the difference between static and instance members, please refer for example to https://msdn.microsoft.com/aa645629(v=vs.71).aspx

Flat Eric
  • 7,971
  • 9
  • 36
  • 45
2

The field initializer has to be assigned without the instance of the class.

You got that error because your:

 public string[] postfixList = postfix("postfixList"); 

Assumes the ValueObj class instance already exists and call postfix (as postfix is part of the instance of the ValueObj class, not part of the ValueObj class) while in fact it has not existed yet on the time of calling.

There are two ways to solve this, one way is by initializing postfix in the constructor (which the other answer shows).

And as an alternative answer besides initializing postfix in the ValueObj constructor, if your postfix method is going to be the same for all ValueObj instances, you may as well declare it as static and return string[] as follow:

class ValueObj
{
    public static string[] postfix(string table) //note the static and string[]
    {
        SQLiteConnection sqlite_conn;
        SQLiteCommand sqlite_cmd;
        SQLiteDataReader sqlite_datareader;

        sqlite_conn = new SQLiteConnection("Data Source=database.db;Version=3;New=False;Compress=True;");
        sqlite_conn.Open();
        sqlite_cmd = sqlite_conn.CreateCommand();

        sqlite_cmd.CommandText = "SELECT * FROM " + table;
        sqlite_datareader = sqlite_cmd.ExecuteReader();

        List<string> list = new List<string>();

        while (sqlite_datareader.Read())
        {
            list.Add(sqlite_datareader.GetString(1));
        }

        return list.ToArray(); // returns string[]
    }

    public string[] postfixList = postfix("postfixList"); // now it is ok

}
Ian
  • 30,182
  • 19
  • 69
  • 107
  • @Ahmediqbal yes, it is. ;) but please note my comment: this solution is good as long as all your instances are using `postfix` identically. Since you use it with constant input `postfixList` in the initialization, I assume it is. ;) if at one point of your development, this stops being the case, please consider other answers. :) – Ian Jan 23 '16 at 15:47
  • constructor solution also work for me, i confused which one i choice :( – Ahmed iqbal Jan 23 '16 at 15:51
  • @Ahmediqbal As I said, it depends on whether you use `postfix` equally across all instances or not. If it is, static is better. But if it is not, initializing it in constructor is better. ;) which one is your case, sir? The answer depends on it. – Ian Jan 23 '16 at 15:53
  • @lan in my case, i renamed postfix method as 'getData' and i need to call this method 4 times, with different tables names. like 'prefix', postfix, ... – Ahmed iqbal Jan 23 '16 at 16:01
  • @Ahmediqbal the table name is ok in using `static`. Because you can just call it with different inputs. What I meant was if you use specific your `ValueObj` instance possess in the method without putting it as input in the `postfix`. If this not be the case, then you can safely use `static` :) – Ian Jan 23 '16 at 16:04
  • @lan Thanks for valuable suggestions :) – Ahmed iqbal Jan 23 '16 at 16:11
  • @Ahmediqbal no problem. ;) – Ian Jan 23 '16 at 16:12
2

In C# it is not valid to initialize a non-static field with a method. If you are using Visual Studio it should highlight the postfix method in this line:

public string[] postfixList = postfix("postfixList");

If you need to use a method you have to move the initialization to the constructor.

public string[] postfixList;
public ValueObj()
{
    postfixList = postfix("postfixList");
}

When initializing at the declaration time what's allowed is to use a value for a value type, e.g.:

public int myLuckyNumber = 13;

or if initializing a reference type you can create a new instance of the type:

public MyClass myField = new MyClass();

In this thread you can find more suggestions to what's best practice when initializing a field in C#.

Not related to the question but note that in C# preferred formatting convention is to use camel cases and start the name of a method with a capital letter.

Community
  • 1
  • 1
PiotrWolkowski
  • 8,408
  • 6
  • 48
  • 68
1

There are many errors in your code.

  1. class ValueObj should be public class ValueObj. Yes a class can be private in c#
  2. public void postfix(string table){...} returns void. It means that a function doesnt return a thing. You cant use it to set value to public string[] postfixList. It should return an array of string.

Also postfixList is not a static property. It means that It will only be initialized once the class ValueObj has been initialized.

The problem is in a class life cycle, class properties don't exists until the object is created(unless static). In your case when you create an object valueOBJ FIRST it tries to initialize all the properties, then it calls the class constructor. Your property postfixList tries to call a class method that has not been constructed yet.

If you want it to look like a c# code do it like this:

public class ValueObj{

    private string[] _postfixList;

    public string[] PostfixList{ get{
        if(_postFixList == null){
            _postFixList = postfix("postfixList")
        }
        return _postfixList
    }}
}
Stralos
  • 4,895
  • 4
  • 22
  • 40