development

null 검사가없는 경우에도 캐스트 대신 "as"를 사용하는 것이 합리적입니까?

big-blog 2020. 3. 1. 15:57
반응형

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; 
}

사람들이 외모를 좋아하기 때문에 읽기 쉽습니다.

C와 유사한 언어의 캐스팅 / 변환 연산자는 가독성이 매우 뛰어납니다. C #이 다음 Javascript 구문 중 하나를 채택하면 더 좋습니다.

object o = 1;
int i = int(o);

또는 다음 to과 같은 캐스팅을 갖는 연산자를 정의하십시오 as.

object o = 1;
int i = o to int;

사람들 as은 예외로부터 안전하다고 느끼기 때문에 너무 좋아 합니다. 남자는 당신이 상자 안에 따뜻하고 건장한 느낌을주기를 원하기 때문에 멋진 보증을합니다. 밤에 베개 아래에 작은 상자를 두었다고하자 보증 요정이 내려 와서 1/4을 떠날 수도 있습니다.

직접 캐스트를 사용할 때 돌아 가기 주제에 ...의 존재 가능성 잘못된 캐스트 예외는. 따라서 사람들 은 자체적으로 예외를 던지지 as않기 때문에 모든 주조 요구에 담요 솔루션으로 적용 됩니다 as. 그러나 재미있는 점은 예제 (x as T).SomeMethod();에서 null 참조 예외에 대해 잘못된 캐스트 예외를 거래하고 있다는 것입니다. 예외를 볼 때 실제 문제를 난독 화시키는 것은 무엇입니까?

나는 일반적으로 as너무 많이 사용하지 않습니다 . 나에게 is테스트를 선호합니다. 더 읽기 쉽고 캐스트를 시도하고 null을 확인하는 것이 더 합리적입니다.


이것은 나의 최고 동료 중 하나 여야 합니다.

Stroustrup의 D & E 및 / 또는 내가 지금 찾을 수없는 블로그 게시물 tohttps://stackoverflow.com/users/73070/johannes-rossel (즉, 의미론 as동일한 구문 이지만) DirectCast).

이것이 구현되지 않은 이유는 캐스트가 통증을 유발하고 추악 해져 사용하지 못하기 때문입니다.

'영리한'프로그래머 (종종 저술가 (Juval Lowy IIRC)) as가 이런 방식 으로 학대함으로써이 문제를 해결하는 것이 유감입니다 (C ++은 as아마도 이런 이유로을 제공하지 않습니다 ).

심지어 VB는 당신이를 선택하는 힘있는 균일 한 구문을 가지고 더 일관성이 TryCastDirectCast하고 당신의 마음을 확인을 !


나는 믿고 as키워드가 좀 더 우아한 찾고 버전으로 간주 할 수있는 dynamic_castC ++에서.


기술적 인 이유는 없지만 읽기 쉽고 직관적이기 때문에 더 인기가있을 것입니다. (단지 질문에 대답하는 것이 더 나아지는 것은 아닙니다)


"as"를 사용하는 한 가지 이유 :

T t = obj as T;
 //some other thread changes obj to another type...
if (t != null) action(t); //still works

(잘못된 코드) 대신 :

if (obj is T)
{
     //bang, some other thread changes obj to another type...
     action((T)obj); //InvalidCastException
}

참고 URL : https://stackoverflow.com/questions/2139798/does-it-make-sense-to-use-as-instead-of-a-cast-even-if-there-is-no-null-check



반응형