I have some auto-instantiation code which I would like to apply to about 15 properties in a fairly big class. The code is similar to the following but the type is different for each instance:
protected ComplexType _propertyName;
public ComplexType PropertyName
{
get
{
if (_propertyName == null) {
_propertyName = new ComplexType();
}
return _propertyName;
}
}
To repeat this in C++ (as there are ~15 instances), I would have used a preprocessor macro but I notice C# doesn't support them.
I am wondering if anyone has a recommendation on how to do this cleanly in C#?
This might make things a bit neater, you could add this method to introduce some reuse:
protected ComplexType _propertyName;
public ComplexType PropertyName
{
get
{
return GetProperty(ref _propertyName);
}
}
.
.
private T GetProperty<T>(ref T property) where T : new()
{
if (property == null)
property = new T();
return property;
}
You can use the ?? operator to simplify the code into one line:
protected ComplexType _propertyName;
public ComplexType PropertyName
{
get
{
return _propertyName ?? (_propertyName = new ComplexType());
}
}
As a side note I would probably avoid protected fields. If you need to set the property from a derived class I would rather create a protected setter.
You can make a generic struct that handles the lazy creation:
public struct LazyCreate<T> where T : class, new() {
private T _value;
public T Value {
get {
if (_value == null) {
_value = new T();
}
return _value;
}
}
}
protected LazyCreate<ComplexType> _propertyName;
public ComplexType PropertyName {
get {
return _propertyName.Value;
}
}
Even though it doesn't directly solve your problem, you could have a look at the new Lazy<T> class that ships with .NET 4.0. It is specifically designed for lazy initialization scenarios.
You could use the much overlooked T4 (Text Template Transformation Toolkit) to generate the code. It is included with Visual Studio 2008.
There was a 2009-06 .NET Rocks episode about it: "Peter Vogel uses Code Generation".
You could implement lazy initialization in a manner similar to this:
public class Lazy<T> where T : new()
{
private T _value;
private bool _isInitialized;
private T GetValue()
{
if (!_isInitialized)
{
_value = new T();
_isInitialized = true;
}
return _value;
}
public static implicit operator T (Lazy<T> t)
{
return t.GetValue();
}
}
which would allow you to write code like this:
private Lazy<ComplexType> _lazyCt = new Lazy<ComplexType>();
public ComplexType LazyCt
{
get { return _lazyCt; }
}
The specifics of the initialization are irrelevant, I wrote it like this to show that you can make it transparently convertible to the non-lazy version, and perform the initialization on the first conversion. :)
Try to use Hashtable or Dictionary <string, ComplexType> to group all properties. Something like this:
protected Dictionaty<string, ComplexType> _properties = new Dictionaty<string, ComplexType>();
public ComplexType Property(string name)
{
get
{
if (!properties.ContainsKey(name))
_properties[name] = new ComplexType();
return __properties[name];
}
}
来源:https://stackoverflow.com/questions/1388511/c-sharp-equivalent-for-c-macros-and-using-auto-properties