C #에서는
자동 속성을 지정된 기본값을 사용하여 지연로드 된 자동 속성으로 전환하는 방법이 있습니까?
본질적으로 나는 이것을 돌리려고 노력하고 있습니다 …
private string _SomeVariable
public string SomeVariable
{
get
{
if(_SomeVariable == null)
{
_SomeVariable = SomeClass.IOnlyWantToCallYouOnce();
}
return _SomeVariable;
}
}
기본값을 지정할 수 있고 나머지는 자동으로 처리합니다.
[SetUsing(SomeClass.IOnlyWantToCallYouOnce())]
public string SomeVariable {get; private set;}
답변
아니 없어. 자동 구현 속성은 가장 기본적인 속성 인 getter 및 setter를 사용한 지원 필드 만 구현합니다. 이러한 유형의 사용자 지정을 지원하지 않습니다.
그러나 4.0 Lazy<T>
유형을 사용하여이 패턴을 만들 수 있습니다.
private Lazy<string> _someVariable =new Lazy<string>(SomeClass.IOnlyWantToCallYouOnce);
public string SomeVariable => _someVariable.Value;
이 코드는 표현식이 _someVariable
처음 Value
호출 될 때의 값을 느리게 계산합니다 . 한 번만 계산되며 향후 Value
속성 사용을 위해 값을 캐시합니다.
답변
아마도 가장 간결한 것은 null-coalescing 연산자를 사용하는 것입니다.
get { return _SomeVariable ?? (_SomeVariable = SomeClass.IOnlyWantToCallYouOnce()); }
답변
C # 6에는 Expression Bodied Auto-Properties 라는 새로운 기능 이있어 좀 더 깔끔하게 작성할 수 있습니다.
public class SomeClass
{
private Lazy<string> _someVariable = new Lazy<string>(SomeClass.IOnlyWantToCallYouOnce);
public string SomeVariable
{
get { return _someVariable.Value; }
}
}
이제 다음과 같이 작성할 수 있습니다.
public class SomeClass
{
private Lazy<string> _someVariable = new Lazy<string>(SomeClass.IOnlyWantToCallYouOnce);
public string SomeVariable => _someVariable.Value;
}
답변
그렇지 않으면 속성에 대한 매개 변수는 값이 일정해야하며 코드를 호출 할 수 없습니다 (정적 코드라도).
그러나 PostSharp의 Aspect로 무언가를 구현할 수 있습니다.
한번 봐봐:
답변
다음은 귀하의 문제에 대한 해결 방법입니다. 기본적으로 아이디어는 첫 번째 액세스시 함수에 의해 설정되는 속성이며 후속 액세스는 첫 번째 액세스와 동일한 반환 값을 생성합니다.
public class LazyProperty<T>
{
bool _initialized = false;
T _result;
public T Value(Func<T> fn)
{
if (!_initialized)
{
_result = fn();
_initialized = true;
}
return _result;
}
}
그런 다음 사용하려면 :
LazyProperty<Color> _eyeColor = new LazyProperty<Color>();
public Color EyeColor
{
get
{
return _eyeColor.Value(() => SomeCPUHungryMethod());
}
}
물론 함수 포인터를 전달하는 오버 헤드가 있지만, 그것은 나를 위해 일을하며 메서드를 반복해서 실행하는 것에 비해 너무 많은 오버 헤드를 느끼지 않습니다.
답변
저는이 아이디어의 열렬한 팬이며 proplazy.snippet이라고 부르는 다음 C # 스 니펫을 제공하고 싶습니다 (이 코드를 가져 오거나 스 니펫 관리자에서 가져올 수있는 표준 폴더에 붙여 넣을 수 있습니다).
다음은 출력 샘플입니다.
private Lazy<int> myProperty = new Lazy<int>(()=>1);
public int MyProperty { get { return myProperty.Value; } }
스 니펫 파일 내용은 다음과 같습니다. (proplazy.snippet으로 저장)
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>proplazy</Title>
<Shortcut>proplazy</Shortcut>
<Description>Code snippet for property and backing field</Description>
<Author>Microsoft Corporation</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>type</ID>
<ToolTip>Property type</ToolTip>
<Default>int</Default>
</Literal>
<Literal>
<ID>field</ID>
<ToolTip>The variable backing this property</ToolTip>
<Default>myVar</Default>
</Literal>
<Literal>
<ID>func</ID>
<ToolTip>The function providing the lazy value</ToolTip>
</Literal>
<Literal>
<ID>property</ID>
<ToolTip>Property name</ToolTip>
<Default>MyProperty</Default>
</Literal>
</Declarations>
<Code Language="csharp"><![CDATA[private Lazy<$type$> $field$ = new Lazy<$type$>($func$);
public $type$ $property$ { get{ return $field$.Value; } }
$end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
답변
순수한 C #으로는 이것이 가능하지 않다고 생각합니다. 그러나 PostSharp 와 같은 IL 재 작성기를 사용하여 수행 할 수 있습니다. 예를 들어 속성에 따라 함수 앞뒤에 핸들러를 추가 할 수 있습니다.