In many cases I like to make types immutable. Where possible, I like to make them properly immutable, which means avoiding automatically implemented properties entirely - otherwise the type is still mutable within the same class, which feels like a bug waiting to happen.
"Proper" immutability will include making the backing field readonly, which means you have to set it in the constructor... usually initializing it from another parameter. I find it quite rare that I can lazily create an instance without any more information, as you do in your question. In other words, this is a more common pattern for me:
public class Person
{
private readonly string name;
public string Name { get { return name; } }
public Person(string name)
{
this.name = name;
}
}
This becomes unwieldy when you have a lot of properties - passing them all into a single constructor can get annoying. That's where you'd want to use the builder pattern, with a mutable type used to collect the initialization data, and then a constructor taking just the builder. Alternatively, the named arguments and optional parameters available in C# 4 should make this slightly easier.
To get back to your exact situation, I'd usually write:
class Foo
{
private readonly MyObject myObject;
public SomeObject MyObject { get { return myObject; } }
public Foo()
{
myObject = new MyObject();
// logic
}
}
That is, unless constructing SomeObject
is particularly expensive. It's just simpler than doing it lazily in the property and potentially having to worry about threading issues.
Now, I've been assuming that immutability is a useful goal here - but you've been talking about adding a setter. I'm not sure why you think that precludes using a field, but it certainly doesn't. For instance, you could combine the lazy instantiation from your first piece of code and having a setter like this:
class Foo
{
private SomeObject _myObject;
public SomeObject MyObject
{
get
{
if( _myObject == null )
{
_myObject = new SomeObject();
}
return _myObject;
}
set
{
// Do you want to only replace it if
// value is non-null? Or if _myObject is null?
// Whatever logic you want would go here
_myObject = value;
}
}
public Foo()
{
// logic
}
}
I think the major decisions should be:
- Do you want the type to be properly immutable?
- Do you need lazy initialization?
- Do you need any other logic in your properties?
If the answer to all of these is no, use an automatically implemented property. If the third answer changes to yes, you can always convert the automatically implemented property into a "normal" one later.