17

I have a Repository Class and a Services Class as below :

public class DinnerRepository
{
    DinnerDataContext db = new DinnerDataContext();

    public Dinner GetDinner(int id)
    {
        return db.Dinners.SingleOrDefault(d => d.DinnerID == id);   
    }

// Others Code        
}



public class Service
{
        DinnerRepository repo = new DinnerRepository(); 
        Dinner dinner = repo.GetDinner(5);

// Other Code
}

This throws error:

A field initializer cannot reference the non-static field, method, or property.

Even though I have intatiated the DinnerRepository Class to expose its method GetDinner() in the Service Class. This works fine with below code. Is there any alternative to it or is it a standard practice? I cannot use static methods here..

public class Service
{

    public Service()
    {
        DinnerRepository repo = new DinnerRepository(); 
        Dinner dinner = repo.GetDinner(5);
    }

}
mmking
  • 1,564
  • 4
  • 26
  • 36
sumit kishore
  • 171
  • 1
  • 1
  • 3

2 Answers2

22

Personally I'd just initialize the fields in a constructor:

public class Service
{
    private readonly DinnerRepository repo;
    private readonly Dinner dinner;

    public Service()
    {
        repo = new DinnerRepository();
        dinner = repo.GetDinner(5);
    }
}

Note that this isn't the same as the code you show at the bottom of the question, as that's only declaring local variables. If you only want local variables, that's fine - but if you need instance variables, then use code as above.

Basically, field initializers are limited in what they can do. From section 10.5.5.2 of the C# 4 spec:

A variable initializer for an instance field cannot reference the instance being created. Thus it is a compile-time error to reference this in a variable initializer, because it is a compile-time error for a variable initializer to reference any instance member through a simple-name.

(That "thus" and "therefore" looks the wrong way round to me - it's illegal to reference a member via a simple-name because it references this - I'll ping Mads about it - but that's basically the relevant section.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    Yeah, the current version reads like "since we have a compile time error on `simple-name`s, we make referencing `this` an error", and not the other way arround. – SWeko Sep 13 '11 at 11:12
  • @JonSkeet Is the reason for this behavior is that fields are initialized before the constructor. So there is no instance member when you try to initialize fields. That's why you cannot use them before class is instantiated Right? – yigitt Dec 19 '16 at 17:24
  • 1
    @UfukSURMEN: Not really... the object already exists, but it would invite some pretty hard-to-reason-about bugs. (It's very annoying sometimes, admittedly...) – Jon Skeet Dec 19 '16 at 18:03
2

Even if the initializaton expressions are guaranteed to be in the "textual order", it is illegal for an instance fields initializers to access the this reference, and you are implicitly using it in

Dinner dinner = repo.GetDinner(5); 

which is equivalent to

Dinner dinner = this.repo.GetDinner(5);

The best practice IMHO, is to reserve field initializations to constant values or to a simple new statement. Anything hairier than that should go to a constructor.

SWeko
  • 30,434
  • 10
  • 71
  • 106