平台:带有Resharper 4.1,.NET 3.5的Visual Studio 2008 SP1
我有一个带静态方法的类,GetProperty<T>
可以懒惰地返回属性值。
private static T GetProperty<T>(T backingField, Func<T> factory)
where T : class
{
if (backingField == null)
backingField = factory();
return backingField;
}
但是当我使用上面的方法返回一个属性时, 我收到两条警告,说没有分配私人支持字段。 但是只有在需要时才会分配它们。
此警告是否可忽略?
- 或 -
我的加载财产是否存在缺陷?
答案 0 :(得分:13)
你的方法存在缺陷。要采用此方法,您需要将backingField
设为ref
参数。
private static T GetProperty<T>(ref T backingField, Func<T> factory)
然后在GetProperty
上传递ref _ImagXpress
或ref _PdfXpress
。
你现在这样做只是为参数赋予一个新值,而不是为实际的后备字段赋值。
答案 1 :(得分:5)
你的方法存在缺陷。你的字段永远不会被设置为任何东西。 backingField
方法中正在设置GetProperty<T>
参数,但这不会更新您传入的字段。您需要使用附加的ref
关键字传递该参数就像这样:
private static T GetProperty<T>(ref T backingField, Func<T> factory)
答案 2 :(得分:3)
正如我在另一个答案的评论中所述,对参数的需求是代码气味。首先,如果你在一个方法中执行此操作,那么你就违反了单一责任原则,但更重要的是,代码只能在你的继承层中重复使用。
这里有一个模式:
public class LazyInit<T>
where T : class
{
private readonly Func<T> _creationMethod;
private readonly object syncRoot;
private T _instance;
[DebuggerHidden]
private LazyInit()
{
syncRoot = new object();
}
[DebuggerHidden]
public LazyInit(Func<T> creationMethod)
: this()
{
_creationMethod = creationMethod;
}
public T Instance
{
[DebuggerHidden]
get
{
lock (syncRoot)
{
if (_instance == null)
_instance = _creationMethod();
return _instance;
}
}
}
public static LazyInit<T> Create<U>() where U : class, T, new()
{
return new LazyInit<T>(() => new U());
}
[DebuggerHidden]
public static implicit operator LazyInit<T>(Func<T> function)
{
return new LazyInit<T>(function);
}
}
这允许您这样做:
public class Foo
{
private readonly LazyInit<Bar> _bar1 = LazyInit<Bar>.Create<Bar>();
private readonly LazyInit<Bar> _bar2 = new LazyInit<Bar>(() => new Bar("foo"));
public Bar Bar1
{
get { return _bar1.Instance; }
}
public Bar Bar2
{
get { return _bar2.Instance; }
}
}
答案 3 :(得分:1)
提出不同的解决方案:
我会说,通过将该逻辑封装到一个单独的方法中,你并没有节省很多。你增加了你的复杂性而没有多少收获。我建议这样做:
protected PdfXpress PdfXpress
{
get
{
if (_PdfXpress == null)
_PdfXpress = PdfXpressSupport.Create();
return _PdfXpress;
}
}
protected ImagXpress ImagXpress
{
get
{
if (_ImagXpress == null)
_ImagXpress = IMagXpressSupport.Create();
return _ImagXpress;
}
}
您添加了几行,但大大降低了复杂性。