Platform: Visual Studio 2008 SP1 with Resharper 4.1, .NET 3.5
平台:带有Resharper 4.1,.NET 3.5的Visual Studio 2008 SP1
I have a class with a static method, GetProperty<T>
that returns a property value lazily.
我有一个带有静态方法的类,GetProperty
private static T GetProperty<T>(T backingField, Func<T> factory)
where T : class
{
if (backingField == null)
backingField = factory();
return backingField;
}
But when I use above method to return a property, I am getting two warnings that says that private backing fields are not assigned. But they are assigned later on only when they are needed.
但是,当我使用上述方法返回属性时,我收到两条警告,指出未分配私有支持字段。但是只有在需要时才会分配它们。
Is this warning ignorable?
-- Or --
Is my appoach to loading a property flawed?
这个警告是否可以忽略? - 或者 - 我的加载财产是否存在缺陷?
4 个解决方案
#1
Your method is flawed. To take this approach you need to make backingField
a ref
parameter.
你的方法有缺陷。要采用这种方法,您需要使backingField成为ref参数。
private static T GetProperty<T>(ref T backingField, Func<T> factory)
Then on GetProperty
, pass ref _ImagXpress
or ref _PdfXpress
.
然后在GetProperty上传递ref _ImagXpress或ref _PdfXpress。
The way you're doing it now just assigns a new value to the parameter, not to the actual backing field.
你现在这样做只是为参数赋予一个新值,而不是为实际的后备字段赋值。
#2
Your approach is flawed. You're fields will never be set to anything. the backingField
argument is being set in the GetProperty<T>
method, but this does not update the field you're passing in. You'll want to pass in that argument with the ref
keyword attached to it like this:
你的方法有缺陷。你的字段永远不会被设置为任何东西。 backingField参数是在GetProperty
private static T GetProperty<T>(ref T backingField, Func<T> factory)
#3
As I stated in comments on another answer, the need for a ref parameter is a code smell. First of all, if you're doing this in a method, you're breaking the single responsibility principle, but more importantly, the code is only reusable within your inheritance heirarchy.
正如我在另一个答案的评论中所说,对参数的需求是代码气味。首先,如果你在一个方法中这样做,你就违反了单一责任原则,但更重要的是,代码只能在你的继承层中重复使用。
There's a pattern to be derived here:
这里有一个模式:
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);
}
}
This allows you to do this:
这允许您这样做:
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; }
}
}
#4
To propose a different solution:
提出一个不同的解决方案:
I'd say that you're not saving a whole lot by encapsulating that logic into a separate method. You're increasing your complexity without much gain. I'd suggest doing it this way:
我会说,通过将该逻辑封装到一个单独的方法中,你并没有节省很多。你增加了你的复杂性而没有多少收获。我建议这样做:
protected PdfXpress PdfXpress
{
get
{
if (_PdfXpress == null)
_PdfXpress = PdfXpressSupport.Create();
return _PdfXpress;
}
}
protected ImagXpress ImagXpress
{
get
{
if (_ImagXpress == null)
_ImagXpress = IMagXpressSupport.Create();
return _ImagXpress;
}
}
You're adding a few lines, but decreasing complexity considerably.
您添加了几行,但大大降低了复杂性。
#1
Your method is flawed. To take this approach you need to make backingField
a ref
parameter.
你的方法有缺陷。要采用这种方法,您需要使backingField成为ref参数。
private static T GetProperty<T>(ref T backingField, Func<T> factory)
Then on GetProperty
, pass ref _ImagXpress
or ref _PdfXpress
.
然后在GetProperty上传递ref _ImagXpress或ref _PdfXpress。
The way you're doing it now just assigns a new value to the parameter, not to the actual backing field.
你现在这样做只是为参数赋予一个新值,而不是为实际的后备字段赋值。
#2
Your approach is flawed. You're fields will never be set to anything. the backingField
argument is being set in the GetProperty<T>
method, but this does not update the field you're passing in. You'll want to pass in that argument with the ref
keyword attached to it like this:
你的方法有缺陷。你的字段永远不会被设置为任何东西。 backingField参数是在GetProperty
private static T GetProperty<T>(ref T backingField, Func<T> factory)
#3
As I stated in comments on another answer, the need for a ref parameter is a code smell. First of all, if you're doing this in a method, you're breaking the single responsibility principle, but more importantly, the code is only reusable within your inheritance heirarchy.
正如我在另一个答案的评论中所说,对参数的需求是代码气味。首先,如果你在一个方法中这样做,你就违反了单一责任原则,但更重要的是,代码只能在你的继承层中重复使用。
There's a pattern to be derived here:
这里有一个模式:
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);
}
}
This allows you to do this:
这允许您这样做:
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; }
}
}
#4
To propose a different solution:
提出一个不同的解决方案:
I'd say that you're not saving a whole lot by encapsulating that logic into a separate method. You're increasing your complexity without much gain. I'd suggest doing it this way:
我会说,通过将该逻辑封装到一个单独的方法中,你并没有节省很多。你增加了你的复杂性而没有多少收获。我建议这样做:
protected PdfXpress PdfXpress
{
get
{
if (_PdfXpress == null)
_PdfXpress = PdfXpressSupport.Create();
return _PdfXpress;
}
}
protected ImagXpress ImagXpress
{
get
{
if (_ImagXpress == null)
_ImagXpress = IMagXpressSupport.Create();
return _ImagXpress;
}
}
You're adding a few lines, but decreasing complexity considerably.
您添加了几行,但大大降低了复杂性。