Reputation: 8655
I have a property defined as...
public List<Obj> Objs { get; set; }
What I would like to be able to do is to put some logic into the get method, so it would look something like...
public List<Obj> Objs
{
get
{
if (Objs == null)
{
Objs = new List<Obj>();
}
if (Objs.Count < 1)
{
Objs.Add(new Obj());
}
return Objs;
}
set { Objs = value; }
}
Now when I do this I get an error telling me that the Function is recursive on all paths.
Is there a way to do this without creating a private backing field?
Upvotes: 6
Views: 8097
Reputation: 45096
private List<Obj> objs = new List<Obj>() { new Obj() };
public List<Obj> Objs { get { return objs; } }
or if you want to protect from someone removing the last Obj
private List<Obj> objs = new List<Obj>();
public List<Obj> Objs
{
get
{
if (objs.Count == 0) objs.Add(new Obj());
return objs;
}
}
What would be the purpose of a public set?
Upvotes: 0
Reputation: 5479
No, not really.
In your code, when you check for if (Objs == null)
- you are effectively using the get method in which you are currently in. So Objs { get; }
calls itself, and that's why it's always recursive.
Remember that auto properties (get; set;
) is really just a shorthand for having a backing field and separate get and set methods. Without that magic, your code would look like this:
private List<Obj> _objs;
public List<Obj> GetObjs() { return _objs; }
public void SetObjs(List<Objs> objs) { _objs = objs; }
What you are really implementing in your post is this - notice how GetObjs() is calling itself multiple times. So for every time it calls itself, it will eventually lead to it calling itself again. And again, and again.:
public List<Obj> GetObjs() {
if (GetObjs() == null)
{
SetObjs(new List<Obj>());
}
if (GetObjs().Count < 1)
{
GetObjs().Add(new Obj());
}
return GetObjs();
}
Upvotes: 0
Reputation: 6795
You have to make a private field:
private List<Obj> _objs;
public List<Obj> Objs
{
get
{
if (_objs== null)
{
_objs= new List<Obj>();
}
if (_objs.Count < 1)
{
_objs.Add(new Obj());
}
return _objs;
}
set { _objs= value; }
}
Why is it impossible? Lets make the same thing in Java:
private List<Obj> objs;
public List<Obj> getListObjs()
{
...
// Recursion
return getListObjs();
}
Upvotes: 13
Reputation: 16636
Your property refers to itself in the definition of the get
part of the property. This is illegal as it would cause the getter to end up in an endless loop. You either have a auto-implemented property (your first example), or a property with a backing field (which is automatically generated by the compiler for auto-implemented properties). You need to add a (preferrably private) field as a backing store for your property:
private List<Obj> objs;
public List<Obj> Objs
{
get
{
if (objs == null)
{
objs = new List<Obj>();
}
if (objs.Count < 1)
{
objs.Add(new Obj());
}
return objs;
}
set { objs = value; }
}
Upvotes: 1
Reputation: 1795
you should use private field to store List of Objs. You can't get data from get method of get method... :) is recursion.
private List<Obj> _objs;
public List<Obj> Objs
{
get {
if (_objs== null)
{
_objs = new List<Obj>();
}
if (_objs.Count < 1)
{
_objs.Add(new Obj());
}
return _objs;
}
set { _objs= value; }
}
Upvotes: 0
Reputation: 21742
No there's no way of doing it without a backing field. Unrelated to the question but related to the situation. You should in general not expose a setter for a collection but only a getter. If you have a setter you are very often exposing internal state of the object, that should be kept hidden.
Upvotes: 3