2009-12-09 8 views
27

나는 다음과 같은 확장 방법이 있습니다이 확장 방법을 리팩토링 할 수 있습니까?

public static void ThrowIfArgumentIsNull<T>(this T value, string argument) 
    where T : class 
{ 
    if (value == null) 
    { 
     throw new ArgumentNullException(argument); 
    } 
} 

이 그 사용의 예입니다 ....

// Note: I've poorly named the argument, on purpose, for this question. 
public void Save(Category qwerty) 
{ 
    qwerty.ThrowIfArgumentIsNull("qwerty"); 
    .... 
} 

100 % 잘 작동합니다.

하지만 예외 메시지를 돕기 위해 변수의 이름을 제공해야하는 것은 마음에 들지 않습니다.

나는 그것을 확장 방법을 리팩토링 할 수 있는지 궁금 해서요, 그래서이 같이 호출 할 수 ...

qwerty.ThrowIfArgumentIsNull(); 

와 자동 변수의 이름을 따라서 '쿼티'와 것을 파악 이 값을 ArgumentNullException의 값으로 사용합니다.

가능합니까? 성찰이 이것을 할 수 있다고 가정하고 있습니까?

+0

참조 http://stackoverflow.com/questions/869610/c-resolving-a-parameter-name-at-runtime/869629#869629 –

+4

http://msmvps.com/blogs/jon_skeet/archive/를 확인하십시오. 2009/12/09/quot-magic-quot-null-argument-testing.aspx - blogged :) –

+0

이것은 매우 간단한 문제에 대한 매우 어려운 해결책이라고 생각합니다. Visual Studio를 사용한다면 코드 스 니펫을 사용하여 매우 쉽게 만들 수 있습니다.) –

답변

34

아니요,이 작업을 수행 할 수 없습니다. 그것은 좋을 것이나, 어떤 종류의 AOP가 관여하지 않으면 불가능합니다. 나는 PostSharp이 속성을 사용 잘하면 멋진 일을 할 수있는 확신과 코드 계약서에 그냥 것 :

Contract.Requires(qwerty != null); 

가 이상적으로는 코드 계약이 전화를 생성하는 PostSharp 속성을하고 싶습니다 - 나는거야 어떤 점에서 그걸 가지고 놀아 라. 그러나 그때까지, 내가 가진 가장 좋은 접근 방법은 당신이 가진 확장 방법이다. ...

(나는 PostSharp + 코드 계약 방식을 시도해 본다. 그것에 대해 블로그, btw ... Mono Cecil도 합리적으로 쉽게 만들 수도 있습니다.)

편집 : Laurent의 대답을 확장하려면 잠재적으로 :

new { qwerty }.CheckNotNull(); 

그리고 당신은 null이 허용되지 않는 매개 변수를 많이 가지고 있다면, 당신은 할 수 :

new { qwerty, uiop, asdfg }.CheckNotNull(); 

이 속성을 해결하기 위해 반사를 사용해야합니다. 모든 액세스에 대해 반성하는 일을 피하고 각 속성에 대한 대리인을 만들고 전반적으로 그것을 현혹시키는 방법이 있습니다. 나는 이것을 블로그 포스트에 대해 조사 할 수는 있지만, 다소 기가 막히고, 매개 변수의 속성만을 생각할 수있는 아이디어를 선호한다 ...

EDIT : 코드가 구현되고 blog post이 정당하게 만들어진다. Ick, but fun

+0

Jon은 답장을 위해 :) –

+1

과 +1을 블로그 게시물에 사용합니다 :) 또한 Laurnet의 답변도 확인할 수 있습니다. –

+4

블로그 게시물을 읽었으며 모든 내용을 검토 할 필요가 없습니다. 그 훌라발루. params없이'ThrowIfNull()'메소드를 구현하고 stack-trace toting 개발자가 어떤 인자가 null인지 알기 위해 스택을 조금 움직여 보자. 그냥 생각 : – RCIX

3

단어 : 아니요.

확장 메서드에 값이 전달됩니다. 값이 어디서 왔는지, 또는 호출자가 어떤 식별자를 참조하도록 선택했는지는 알 수 없습니다.

1

난 당신이 아니라 다음을 수행하는 것이 좋습니다 것입니다 :

public static void ThrowIfArgumentIsNull(this object value, string argument) 
{ 
    if (value == null) 
    { 
     throw new ArgumentNullException(argument); 
    } 
} 

값을 추가하지 않는 것,이 경우 제네릭을 사용. 그러나 당신의 원래 질문에 대해서는 그것이 가능하다고 생각하지 않습니다.

+2

제네릭을 사용하면 메소드가 값 유형을 제외 할 수 있습니다. 'where T : class' – Greg

1

는 대답과 같은 라인을 따라 완전한 솔루션도 ArgumentNullException and refactoring 참조하십시오.

에 대해 무엇 :

public void Save(Category qwerty) 
{ 
    ThrowIfArgumentIsNull(() => return qwerty); 
    qwerty.ThrowIfArgumentIsNull("qwerty");  
    // .... 
} 

다음

public static void ThrowIfArgumentIsNull(Expression<Func<object>> test) 
{ 
    if (test.Compile()() == null) 
    { 
     // take the expression apart to find the name of the argument 
    } 
} 

죄송으로 ThrowIfArgumentIsNull을 정의 내가 구체적으로 채우거나 현재 전체 코드를 제공 할 수있는 시간이 없어.

+0

람다에'return' 부분이 필요 없다는 것에 유의하십시오. –

2

코드 스 니펫을 사용하면 가장 쉽게 찾을 수 있습니다.

예에서 tna<tab>qwerty<enter>을 입력 할 수 있습니다.

<?xml version="1.0" encoding="utf-8" ?> 
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> 
    <CodeSnippet Format="1.0.0"> 
     <Header> 
       <Title>Check for null arguments</Title> 
       <Shortcut>tna</Shortcut> 
       <Description>Code snippet for throw new ArgumentNullException</Description> 
       <Author>SLaks</Author> 
       <SnippetTypes> 
         <SnippetType>Expansion</SnippetType> 
         <SnippetType>SurroundsWith</SnippetType> 
       </SnippetTypes> 
     </Header> 
     <Snippet> 
       <Declarations> 
         <Literal> 
           <ID>Parameter</ID> 
           <ToolTip>Paremeter to check for null</ToolTip> 
           <Default>value</Default> 
         </Literal> 
       </Declarations> 
       <Code Language="csharp"><![CDATA[if ($Parameter$ == null) throw new ArgumentNullException("$Parameter$"); 
     $end$]]> 
       </Code> 
     </Snippet> 
    </CodeSnippet> 
</CodeSnippets> 
1

나는 Lokad Shared Libraries에서 Enforce 좋아 : 여기

은 조각이다.

기본 구문 : 인수가 널인 경우이 매개 변수의 이름과 유형 예외가 발생합니다

Enforce.Arguments(() => controller,() => viewManager,() => workspace); 

.

관련 문제