[C#] null 검사가없는 경우에도 캐스트 대신 “as”를 사용하는 것이 합리적입니까? [닫은]

개발 블로그, 온라인 코드 예제 및 (최근) 책에서도 다음과 같은 코드에 대해 계속 걸림돌이됩니다.

var y = x as T;
y.SomeMethod();

또는 더 나쁜 :

(x as T).SomeMethod();

그건 말이되지 않습니다. x유형 이 확실하다면 T직접 캐스트를 사용해야합니다 (T)x.. 확실하지 않은 경우 일부 작업을 수행하기 전에 사용할 수 as있지만 확인해야 null합니다. 위의 코드가하는 것은 (유용한) InvalidCastException를 (유용하지 않은)로 바꾸는 것 NullReferenceException입니다.

이것이 as키워드 의 명백한 남용이라고 생각하는 유일한 사람 입니까? 아니면 내가 명백한 것을 그리워하고 위의 패턴이 실제로 의미가 있습니까?



답변

당신의 이해는 사실입니다. 그것은 나에게 미세 최적화하려고하는 것 같습니다. 유형이 확실하면 일반 캐스트를 사용해야합니다. 더 현명한 예외를 생성하는 것 외에도 빠르게 실패합니다. 유형에 대한 당신의 가정에 대해있는 거 잘못이 경우, 프로그램이 즉시 실패하고 당신은을 위해 장애 것이 아니라 즉시 대기의 원인을 볼 수 있습니다 NullReferenceException또는 ArgumentNullException미래에 또는 논리적 오류 언젠가. 일반적으로 어딘가에 검사가 as뒤 따르지 않는 표현식 null은 코드 냄새입니다.

반면, 캐스트에 대해 확신이없고 실패 할 것으로 예상 as되는 경우 try-catch블록으로 랩핑 된 일반 캐스트 대신 사용해야 합니다 . 또한 as유형 검사 후 캐스트에 사용하는 것이 좋습니다. 대신에:

if (x is SomeType)
   ((SomeType)x).SomeMethod();

이는 생성 isinst명령 에 대한 is키워드 및 castclass명령 캐스트 (효과적으로 두 번 캐스트를 수행)를 들어, 당신은 사용해야합니다 :

var v = x as SomeType;
if (v != null)
    v.SomeMethod();

isinst명령 만 생성합니다 . 이전의 방법은 경쟁 조건으로 인해 is검사가 성공하고 캐스트 라인에서 실패한 후 변수의 유형이 변경 될 수 있으므로 다중 스레드 응용 프로그램에 결함이있을 수 있습니다 . 후자의 방법은이 오류가 발생하지 않습니다.


다음 솔루션은 프로덕션 코드에 사용 하지 않는 것이 좋습니다 . C #에서 이러한 기본 구성을 정말로 싫어한다면 VB 또는 다른 언어로 전환하는 것을 고려할 수 있습니다.

캐스트 구문을 필사적으로 싫어하는 경우 캐스트를 모방하는 확장 메소드를 작성할 수 있습니다.

public static T To<T>(this object o) { // Name it as you like: As, Cast, To, ...
    return (T)o;
}

깔끔한 [?] 구문을 사용하십시오.

obj.To<SomeType>().SomeMethod()


답변

IMHO, 수표 as와 함께 사용하는 것이 null좋습니다.

var y = x as T;
if (y != null)
    y.SomeMethod();


답변

‘as’를 사용하면 사용자 정의 전환이 적용되지 않지만 캐스트에서는 적절한 경우 전환을 사용합니다. 경우에 따라 중요한 차이가 될 수 있습니다.


답변

나는 이것에 대해 조금 썼다 :

http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx

나는 당신의 요점을 이해합니다. 캐스트 운영자는 “이 객체는 해당 유형으로 변환 될 수 있다고 확신하며, 틀린 경우 예외를 기꺼이 감수 할 것입니다”라는 의사 소통에 동의합니다. “이 개체가 해당 형식으로 변환 될 수 있는지 잘 모르겠습니다. 틀린 경우 null을 지정하십시오.”

그러나 미묘한 차이가 있습니다. (x는 T) .Whatever ()는 “x를 T로 변환 할 수있을뿐만 아니라 참조 또는 언 박싱 변환 만 포함하고, x가 null이 아니라는 것을 알고 있습니다.” 그것은 ((T) x) .Whatever ()와 다른 정보를 전달하며 아마도 코드 작성자가 의도 한 것입니다.


답변

나는 종종 “오직”이 캐스팅보다 빠르다는 증거 로이 잘못된 기사에 대한 언급을 보았다 .

이 기사에서 가장 오해의 소지가있는 부분 중 하나는 측정 대상을 나타내지 않는 그래픽입니다. 나는 실패한 캐스트를 측정하고 있다고 생각합니다 (예외가 발생하지 않아 “as”가 훨씬 빠릅니다).

측정하는 데 시간이 걸리면 예상대로 주조가 더 빠름을 알 수 있습니다 한대로 캐스팅이 성공할 때 캐스팅이 “as”보다 는 있습니다.

이것이 캐스트 대신에 as 키워드를 “cargo cult”로 사용하는 한 가지 이유 일 수 있습니다.


답변

직접 전송에는 as키워드 보다 괄호 쌍이 더 필요 합니다. 따라서 유형이 무엇인지 100 % 확신하는 경우에도 시각적 혼란을 줄입니다.

그러나 예외적 인 것에 동의했다. 그러나 적어도 나를 위해, 대부분의 사용은 나중에 as확인하기 위해 끓여서 null예외를 잡는 것보다 더 좋습니다.


답변

“as”를 사용하는 시간의 99 %는 실제 객체 유형이 무엇인지 잘 모르겠습니다.

var x = obj as T;
if(x != null){
 //x was type T!
}

“is”를 사용하여 명시적인 캐스트 예외를 포착하거나 두 번 캐스트하고 싶지 않습니다.

//I don't like this
if(obj is T){
  var x = (T)obj;
}