PositiveGuy
PositiveGuy

Reputation: 47743

Cannot access non-static field

I can't figure out why it's looking for something static:

public class DatabaseBase
{
    private readonly string connectionString;

    public DatabaseBase(string connectionString)
    {
        this.connectionString = connectionString;
    }
}

public class MyDB : DatabaseBase
{
    readonly string connectionString = ConfigurationManager.AppSettings["MyConnectionString"];

    public MyDB() : base(connectionString)
    {          
    }
}

I get Cannot access non-static field 'connectionString' in static context. I don't see anything static in the base Database class so why??

here's another example of when we did kinda the same thing:

partial class Database : DatabaseBase
{
    static string DbConnectionString
    {
        get
        {
            if (dbConnectionString == null)
                dbConnectionString = 
                    ConfigurationManager.AppSettings["MyConnectionString"];
            return dbConnectionString;
        }
    }
    public Database() :base(DbConnectionString)
    {
    }

ok so why did it have to be a static string for the connection string to be passed?

Upvotes: 8

Views: 8245

Answers (2)

Eric Lippert
Eric Lippert

Reputation: 660098

We have worked hard to give error messages that are accurate, so read them carefully. The error message is telling you exactly what is going wrong: you are accessing a non-static field in a context where it is only legal to access statics.

So why is a base constructor call argument list a context where it is only legal to access statics?

When you call a base constructor, the arguments you pass must not reference "this". Why? Because neither the derived constructor nor the base constructor for your "this" has run yet, and therefore "this" is almost certainly in an inconsistent, partially-initialized state. That is a recipe for crazy bugs. We therefore restrict you from accessing "this" until we know that at the very least, the base constructor has run.

This feature encourages sensible, well-ordered, understandable, maintainable and bug-free construction logic; I recommend working with, not against, those safeguards.

Upvotes: 27

Av Pinzur
Av Pinzur

Reputation: 2228

Your problem is in the MyDB constructor. The instance field (MyDB.connectionString) will not be initialized until the call to the base constructor returns, so everything inside base( ... ) is in the static context. Just work with it...

public class MyDB : DatabaseBase
{
    static readonly string connectionString = 
          ConfigurationManager.AppSettings["MyConnectionString"];
    public MyDB() : base(connectionString)
    {
    }
}

or better yet (as suggested by Simon Fox) ...

public class MyDB : DatabaseBase
{
    public MyDB() : base(ConfigurationManager.AppSettings["MyConnectionString"])
    {
    }
}

Upvotes: 4

Related Questions