code

C#은 VB.NET의 DirectCast에 해당합니다.

starcafe 2023. 5. 28. 20:57
반응형

C#은 VB.NET의 DirectCast에 해당합니다.

C#에 VB.NET의 DirectCast와 동등한 기능이 있습니까?

() 캐스트와 'as' 키워드가 있는 것으로 알고 있지만, 이러한 키워드는 Ctype과 TryCast에 연결됩니다.

이러한 키워드는 다음과 같습니다.

CType/() 캐스트:이미 올바른 유형이면 캐스트하고, 그렇지 않으면 유형 변환기를 찾아 호출합니다.유형 변환기를 찾을 수 없으면 InvalidCastException을(를) 던집니다.

TryCast/"as" 키워드:올바른 유형이면 캐스팅하고, 그렇지 않으면 null을 반환합니다.

DirectCast: 올바른 유형이면 캐스팅하고 그렇지 않으면 InvalidCastException을 던집니다.

위의 내용을 설명한 후에도 일부 사람들은 여전히 ()이 동등하다고 응답했는데, 왜 이것이 사실이 아닌지에 대해 더 자세히 설명하겠습니다.

DirectCast는 상속 트리에서 축소 또는 확대 변환만 허용합니다.()와 같이 서로 다른 분기 간의 변환을 지원하지 않습니다.

C# - 다음을 컴파일하여 실행합니다.

//This code uses a type converter to go across an inheritance tree
double d = 10;
int i = (int)d;

VB.NET - 컴파일되지 않습니다.

'Direct cast can only go up or down a branch, never across to a different one.
Dim d As Double = 10
Dim i As Integer = DirectCast(d, Integer)

VB.NET에서 내 C# 코드에 해당하는 것은 Ctype입니다.

'This compiles and runs
Dim d As Double = 10
Dim i As Integer = CType(d, Integer)

당신이 원하는 기능이 C#에 없는 것은 분명해 보입니다.그래도 한번 해보세요...

static T DirectCast<T>(object o, Type type) where T : class
{
    if (!(type.IsInstanceOfType(o)))
    {
        throw new ArgumentException();
    }
    T value = o as T;
    if (value == null && o != null)
    {
        throw new InvalidCastException();
    }
    return value;
}

또는 VB와 다르더라도 다음과 같이 부릅니다.

static T DirectCast<T>(object o) where T : class
{
    T value = o as T;
    if (value == null && o != null)
    {
        throw new InvalidCastException();
    }
    return value;
}

번째 업데이트:

좋아요, 여기 기본적으로 무엇을 하기 위해 제안된 C# 방법이 있습니다.DirectCastVB.NET에서 수행합니다.

static T DirectCast<T>(object o) where T : class
{
    T value = o as T;
    if (value == null && o != null)
    {
        throw new InvalidCastException();
    }
    return value;
}

위 방법의 문제는 다음과 같습니다.

  1. 그것은 있습니다.where T : class 조건,즉 약제, 어것느입니다.DirectCast하지 않다.
  2. 그것은 그것의 주장을 상자로 포장합니다.System.Object다시 말하지만, 이 사실이 아닌DirectCast(적어도 내가 알고 있는 것은 아닙니다.)
  3. 그것은 사용합니다.as불필요하게 (그것이 그것이 그것이 가지고 있는 이유입니다.class를 부르면 ); (T)o를 던질 입니다.InvalidCastException작동하지 않는 경우, 값이 일치하는지 확인하는 이유는 무엇입니까?as당신이 갔더라면 던져졌을 것과 같은 예외를 던졌을 뿐입니다.(T)o시작할 경로는?

이 방법은 실제로 다시 작성하여 다음과 같은 결과를 제공할 수 있습니다.DirectCast다음과 같이:

static T DirectCast<T>(object o) {
    return (T)o;
}

재미있는 관찰: 실제로 이 방법은 값을 상자에 넣고 상자를 여는 것입니다. 다른말하면로,하면,DirectCast<int>(12.0)와 정말 같을 것입니다.(int)(object)12.0(둘 중 하나라도 예외가 될 수 있습니다.)이것을 깨닫는 것은 제안된 것이 됩니다.DirectCast<T>전혀 불필요한 방법입니다.

자, 여기 그 방법의 예가 있습니다.DirectCast그리고 캐스팅은()VB.NET과 C# 사이에 "다름"이 있습니다.

VB:

Dim i As Integer = 12
Dim l As Long = DirectCast(i, Long) ' does not compile '

C#:

int i = 12;
long l = i; // DOES compile

하나는 컴파일하고 다른 하나는 컴파일하지 않습니다.하지만 저 코드를 보세요.객체의 유형을 이미 알고 있을 때 무슨 의미가 있습니까?이것은 현실적인 비교가 아닙니다. 왜냐하면 VB.NET에서는 전화할 이유가 없기 때문입니다.DirectCast위의 코드가 하는 것처럼. (유형으로 알려진 값을 유형의 값으로 변환하려는 경우)System.Int64VB를 합니다.NET에서, 당신은CLng,것은 아니다.DirectCast로) 로 입력합니다.System.Object그 안에서, 그렇다면, 사용하는 것이 타당할 것입니다.DirectCast그리고 아래 코드는 실제로 동등합니다.

VB:

Dim i As Integer = 12
Dim o As Object = i
Dim l As Long = DirectCast(o, Long) ' compiles, throws an exception '

C#:

int i = 12;
object o = i;
long l = (long)o; // compiles, throws an exception

는 그 주장을 고수합니다.DirectCastVB.NET에서는 실제로 사용하는 것이 타당한 시나리오(즉, 컴파일 시 객체의 유형을 알 수 없는 경우)에서 C#의 스트레이트 스타일 캐스트와 동일합니다.


편집: 글쎄요, 컴파일되지 않은 VB 코드를 게시한 것은 부끄러운 일입니다.제가 한 말을 재고한 후, 는 두 번째 답변은 철회하지만 첫 번째 답변은 유지합니다.

의사법말경는우시씀하을용의 하시는 거라면DirectCast알 수 없는 유형의 물체를 원하는 유형으로 캐스팅하려고 하면 C#의 () 캐스트와 동일합니다.

VB:

Dim o As Object = SomeObject()
Dim i As Integer = DirectCast(o, Integer)

C#:

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

왜하면면, 만에약.o는 로입니다로 됩니다.System.Object 다음에 그음에다.()C#에서 작업을 수행하면 상자를 해제하려고 시도합니다.를 들어, "" "" " " " " " " " " 이런 합니다.o 안에 들어 있는 입니다상입니다.System.Double,그리고나서(int)o가 되기 에 예외를 것입니다.o 로서 상자를 열어야 합니다.System.Double으로 에.System.Int32(내 말을 못 믿겠으면 직접 해보세요!)


하지 않습니다. 왜냐하면 ": 아는다과같이은부니다합정확유로참음고래"이기 때문입니다.DirectCast확장 변환을 수행하지 않습니다. 어떤 경우에도, 저는 그것을 후세에 남깁니다.

는 면에반, 확대축변다때룰을환소대를 하여,()C#에서의 작업은 당신이 지적한 것처럼 단순한 캐스팅 이상의 작업을 합니다(즉, 당신은 할 수 있습니다).(int)someDouble에서는 ). 이 시나리오에서,DirectCastC#에서 일반적인 오래된 할당과 같습니다.

VB:

Dim i As Integer = 12
Dim l As Long = DirectCast(i, Long) ' does not compile, actually '

C#:

int i = 12;
long l = i;

직접 구현할 수 있습니다.

static T CastTo<T>(this object obj) { return (T)obj; }

다음과 같이 사용합니다.

3.5.CastTo<int>(); //throws InvalidCastException.

인 것들이 변환기를 변환은 됩니다. 각 제은해런 "결되릭"만▁for▁doesn▁this▁each▁distinct▁generate▁because않ters습▁framework▁the▁convers-니생성다하지▁of'을▁works구현의▁and-해▁actually,t개ics별▁are제해▁user대▁theT하지만 유사한 구현을 공유합니다.T따라서 런타임에는 사용자 지정 변환을 확인할 수 있는 정보가 없습니다.

VB.NET:

Dim xxx as label = Directcast(sender, label)

C#:

label xxx = (label)sender;

실제로 컴파일러는 입력된 변수를 다른 유형으로 변환할 수 없다고 판단할 경우 DirectCast 위반을 탐지합니다.

다음은 실제 등가물입니다.

double d = 10;
int i = (int)d;
Dim d As Double = 10
Dim i As Integer = d

이 구조물의 위험성에 유의하십시오.VB.NET에서 정수에 이중을 할당하기만 하면 실수로 이중 크기가 정수로 축소됩니다.

C# 프로그래머는 .NET의 변수를 실수로 축소하지 않는 컴파일 시간 안전성을 확보하는 반면, VB.NET 프로그래머는 항상 DirectCast를 안전한 프로그래밍 습관으로 사용하는 것과 씨름해야 합니다.

다음은 실제 등가물입니다.

// Will not compile, cannot convert double to int

double d = 10;
int i = d;
' Will not compile, cannot convert double to int

Dim d As Double = 10
Dim i As Integer = DirectCast(d, Integer)

Dan Tao의 발언과 관련하여:

C#에서 DirectCast를 사용할 필요가 없습니다.또한 런타임은 긴 값에서 정수 값으로의 로드를 방지합니다.이것이 OP가 주장하는 것입니다. C#에는 DirectCast가 없고, DirectCast는 다른 유형의 변수를 할당하는 것을 막을 수 있는 반면, "왜냐하면" C#에는 DirectCast가 없기 때문에 다른 유형을 할당할 때 자동으로 오류가 발생합니다.하지만 보시다시피, 그렇지 않습니다.C#의 캐스팅은 DirectCast와 정확히 동일합니다.그러면 InvalidCastException 런타임 오류가 발생합니다.

long l = 10;
object o = l;
int i = (int)o;

이렇게 하면 위와 동일한 런타임 오류가 발생합니다.

Dim l As Long = 10
Dim o As Object = l
Dim i As Integer = DirectCast(o, Integer)

자, 여기서 "재미있는" 부분이 나옵니다.VB.NET을 사용하면 무언가를 성취하기 위해 많은 키워드를 기억해야 합니다.C#에서 주어진 키워드가 다른 시나리오(변수의 다운캐스팅과 같은)에서 사용될 수 있다면, 그들은 단지 그것을 실현하기 위해 다른 키워드를 발명하지 않을 것입니다.

C#에서 다음 작업만 수행하면 됩니다.

long l = 10;
object o = l;
int i = (int)(long)o;

VB.NET에서 변수를 다운캐스팅하고 직교 방식을 사용하려면 다음 작업을 수행해야 합니다. 즉, 키워드 하나만 기억하면 됩니다.

Dim l As Long = 10
Dim o As Object = l
Dim i As Integer = DirectCast(DirectCast(o, Long), Integer)

그러나 그것은 컴파일되지 않을 것입니다. 그렇다면 어떻게 하면 정수로 길게 다운캐스팅을 달성할 수 있을까요?VB.NET의 다른 키워드를 기억해야 합니다. 이 C#을 를 푼 입니다.(typehere)동일한 구성을 사용하여 다운캐스트/업캐스트도 수행할 수 있습니다.(typehere)VB.NET에서는 객체에서 값을 로드하는 것과 다운캐스팅하는 것 사이에 근본적인 단절이 있습니다.따라서 VB.NET에서는 다음을 수행해야 합니다.

Dim l As Long = 10
Dim o As Object = l
Dim i As Integer = CType(o, Integer)

은 C의 흠의 것 . OP의 혼란은 C#의 다중 사용에서 기인한다고 생각합니다.(typehere), 한 구문의 첫 , 첫, 다, 둘, , 일한째의첫분째, 물게시용에팅스캐운이▁the▁of▁first▁(,(구조확,;▁down인castingcheck▁first한일동▁part부▁is▁construct▁for,object o = l 해제에도 하고 DirectCast의동작을 있습니다.)는 객체에서 값의 박스 해제에도 사용되며, DirectCast의 안전한 유형 변환 동작을 가지고 있습니다.그들은 같습니다!

이 다운캐스팅은...

long l = 1;
int i = (int) l;

...는 다음과 같지 않습니다.

Dim l As Long = 1
Dim i As Integer = DirectCast(l, Integer)

다운캐스팅을 수행하려면 다음 작업을 수행해야 합니다.

Dim l As Long = 1
Dim i As Integer = CInt(l) ' Can also use CType

VB.NET 프로그래머가 의도적으로 프로그래밍을 하고 있고 코딩 중 졸리지 않다면 다른 유형을 할당할 수 없다는 것을 완전히 알고 있는데 왜 DirectCast를 사용합니까?VB.NET 프로그래머가 진정으로 원했던 것이 다운캐스트라면, 그/그녀는 애초에 DirectCast를 시도하지 말아야 합니다.이제 DirectCast를 다운캐스팅에 사용할 수 없다는 것을 알게 된 VB.NET 프로그래머는 자신이 작성한 내용을 백스페이스로 만들어 CInt(또는 CType)로 대체해야 합니다.

제가 한번 해보겠습니다.

먼저, 이것에 대해 분명히 말씀드리겠습니다.컴파일되지 않습니다.

//This code uses a type converter to go across an inheritance tree
string s = "10";
int i = (int)s;

VB의 C타입

VB에서는 다음을 사용합니다.

Dim s as String = "10"
Dim i as Integer = CType(s, Integer)

C#에서는 다음을 사용합니다.

string s = "10";
int i = Convert.ToInt32(s);

VB의 다이렉트 캐스트

올바른 유형이면 캐스팅하고 그렇지 않으면 InvalidCastException을 던집니다.

직접 출연진은 가지를 오르거나 내리거나 할 수만 있으며, 다른 가지로 건너갈 수는 없습니다.

그 설명에서, 그것은 C# 캐스트와 직접적으로 동등할 것입니다.그러나 C#에서는 캐스트 연산자를 아래로 드리우기 위해서만 지정하면 됩니다.토해내는 것은 전적으로 선택 사항입니다.예:

// casting down
object t = "some random string needing to be casted down";
string s = (string) t;
// casting up
object a = s;
// explicitly casting up although it's totally optional
object b = (object) s;

C# 캐스트는 유형 변환기를 찾지 않습니다.캐스트하려는 유형에 대해 정의된 명시적/암묵적 연산자 오버로드만 찾습니다.


VB의 트라이캐스트

당신은 이것이 키워드로서 C#에 해당한다는 것을 이미 올바르게 이해했습니다.

C#에는 두 가지 유형의 캐스트가 있습니다.추가 코드가 없으면 C#에 DirectCast 키워드와 동일한 코드가 없습니다.직접 만들지 않고 가장 가까운 것은 사용하는 것입니다.().

다음이 있습니다.

My_Object c = (My_Object)object

그리고.

My_Object c = object as My_Object

첫 번째는 출연진이 실패하면 오류를 던집니다.당신은 "나는 이 물체가 무엇인지 알고 있고, 만약 그것이 아니라면, 뭔가 잘못된 것이 있습니다."라고 말하고 있습니다.

는 두번는째.c가능한 경우 null 값이 할당됩니다(값 유형에는 할당할 수 없음).이 글에서 당신은 "나는 이것이 무엇인지 알고 있다고 생각하지만, 만약 그렇지 않다면, 아무 문제가 없을 수도 있기 때문에 오류를 던지지 마세요."라고 말하고 있습니다.

캐스팅을 설명하는 다른 게시물:

명시적 유형 주조와 암시적 유형 주조의 차이점은 무엇입니까?

정말 샘플 코드를 실행하려고 했습니까?

관련...

//This code uses a type converter to go across an inheritance tree
string s = "10";
int i = (int)s;

...실행될 것이라고 가정했습니다.또한 실행되지 않습니다.

DirectCast그리고.()항상 동일한 CIL을 생성하는 것은 아니므로 VB 컴파일러와 C# 컴파일러 간의 차이라고 생각합니다.

제가 아는 한, 참조 유형은 다음을 사용하여 캐스트됩니다.castclassCIL 명령어는 값 형식의 경우 컴파일러가 입력 형식에 따라 관련 CIL을 생성합니다.

C#에서 주조 위치doubleinteger를 방출합니다.conv.i4값이 너무 큰 경우 출력의 부호 비트 또는 기타 항목을 유쾌하게 덮어쓰는 CIL 명령입니다.Visual Basic에서는 컴파일 오류입니다.

흥미롭게도, 만약 당신이 중간자를 사용한다면.object더블을 고정할 변수, C# 및 Visual Basic 모두에서 캐스트가 실패합니다...하지만 런타임에.두 컴파일러 모두 다음과 같이 출력합니다.unbox변환을 시도하는 대신 지시를 내립니다.

() 캐스팅은 동일해야 합니다. InvalidCastException이 발생합니다.C#에서 사용해 보십시오.

 string t = "hello";
 object x = t;
 int j = (int) x;

저는 이 시나리오가 DirectCast가 비오브젝트(개체 키워드) 유형에 대한 보안을 검사하는 잘못된 컴파일 타임 유형 감각을 가지고 있으며 단지 백스페이스로 사용되는 이유를 가장 잘 요약하고 있다고 생각합니다.

float f = 10;
long l = f;
Option Strict On
Dim f As Single = 10
Dim l As Long = f

C# 코더는 float를 long에 직접 할당할 수 없으며 컴파일하지 않는다는 것을 발견하면 다음과 같이 수행합니다.

long l = (long)f;

맞는 말입니다.

이제 VB.NET 코더를 사용하여 float를 long에 할당할 수 없고 컴파일할 수 없다는 것을 알게 되면 다음과 같이 시도합니다.

Dim l As Long = DirectCast(f, Long)

몇 초 후에...

VB.NET 프로그래머: "제발 제가 명령을 내릴 수 있게 해주세요, 제발 컴파일해주세요, 제발...!!!"

잠시 후 Google-fu 및 MSDN 브라우징 후:

VB.NET 프로그래머: "아..따라서 변수를 주조하는 데 이 CLng 또는 CType 구조를 사용해야 합니다."

Dim l As Long = CLng(f)

그것이 DirectCast가 컴파일 타임 유형 검사 보안에 대한 잘못된 감각을 가지고 있다는 것을 의미합니다.DirectCast는 프로그래머가 언제 어디서 사용해야 하는지 모르는 경우 백스페이스로 사용됩니다.DirectCast는 항상 착용하지 않는 보안 담요입니다.

이 시나리오에서 DirectCast를 사용하지 않을 경우 얼마나 유용합니까?


[편집]

@규칙

모든 VB.NET 프로그래머가 DirectCast의 실제 용도를 모른다는 것은 아닙니다.그들 중 일부는 DirectCast가 객체 유형(및 객체에 상자로 표시된 기본 유형)에만 사용된다는 것을 알고 있습니다.

기존 C# 코드를 VB.NET 코드로 기록하는 VB.NET 코더가 잘못된 결론에 도달하는 한 가지 시나리오는 (옳든 아니든) 서로에 대한 예상 언어 대칭입니다.

코드에서 이 구조를 볼 때...

TextBox txt = (TextBox)sender;

...그/그녀는 이를 다음과 같이 해석할 것입니다.

Dim txt As TextBox = DirectCast(sender, TextBox)

맞는 말입니다.

우리 프로그래머들은 대칭성을 좋아하기 때문에, 우리들 중 일부는 (내가 CLng를 모른다면 나도 그럴지도 모른다) 이 코드를 변환하는 경향이 있을 것입니다.

/* Numbers are stored in file as float(component's file structure
is designed by 3rd party company) */
float f = file.ReadFloat(0);
long l = (long)f; // But we don't care about using the fractional part

...여기까지:

Dim f As Single = file.ReadFloat(0)
Dim l As Long = DirectCast(f, Long)

만약 C# 사람이 C# 코드를 VB.NET으로 변환하는 사람이라면, 그는 여기서 명백한 대칭성 부족으로 좌절할 것입니다.

그러나 C# 코드를 VB.NET으로 변환하는 작업을 맡은 VB.NET 사용자의 경우 C# 컴파일러는 호환되지 않는 형식 할당을 파악하지 않는 반면 VB.NET은 이를 파악한다는 인상을 받게 됩니다.이제 이러한 명백한 발견을 위해 VB.NET 기능을 동료들과 일부 포럼에 자랑할 것입니다.

그러나 VB.NET 프로그래머는 첫 번째 코드의 의도를 잘못 추론하는 실수를 범하지 않습니다.위의 C# 코드 조각 이렇게 인생을 시작했습니다. 처음에는 다음과 같이 작성되었습니다.

float f = file.ReadFloat(0);
long l = f;

그리고 그것은 컴파일되지 않을 것이고, C# 컴파일러는 호환되지 않는 유형 할당을 잡습니다. 이는 동등한 VB.NET과 같은 맥락입니다.Option Strict On또한 컴파일하지 않을 것입니다. (파일은 다음 경우에만 컴파일하지 않을 것입니다.Option Strict으로 설정됨On너무 관대함).그래서 우리는 float를 길게 타이핑해야 합니다.(long)다음 항목이 됩니다.long l = (long)f;

이제 하나의 변수 유형을 다른 호환되는 유형으로 캐스팅합니다. 이 코드를 변환하는 것과 같은 맥락에서...

TextBox txt = (TextBox)sender;

...이 코드로:

Dim txt As TextBox = DirectCast(sender, Textbox)

이 코드를 변환해야 합니다...

long l = (long)f; // Will compile

...이 코드로:

Dim l As Long = DirectCast(f, Long) ' Will not compile

하지만 안타깝게도, 그것은 컴파일되지 않습니다.호환 가능한 원시 유형 간의 캐스팅에서는 DirectCast가 부족합니다.위의 C# 코드와 대칭을 제공하지 않으며 DirectCast라는 이름에도 불구하고 호환 가능한 원시 유형을 캐스팅하는 데 사용할 수 없습니다.

제가 보기에 DirectCast는 CastObject라는 이름이 있어야 합니다. 왜냐하면 객체 유형(및 객체에 상자로 표시된 원시 유형) 간에만 캐스트할 수 있기 때문입니다.DirectCast는 호환 가능한 기본 유형(정수, 이중 및 하위 및 상위 상대)을 할당하는 업무를 수행하지 않습니다.호환 가능한 기본 유형 간에 할당할 때 DirectCast는 더 이상 유용하지 않습니다. 특히 사용자는 이를 백스페이스로 전환하고 적절한 형식으로 교체합니다.

아니면 DirectCast 구조를 수정하여 C, C++, C#, Java, Delphi, D 등과 같은 오래되고 새로운 언어와 같은 호환 가능한 유형을 캐스팅할 수 있습니다.이렇게 하면 유형 캐스팅과 관련하여 VB.NET이 다른 언어와 상당한 대칭성을 제공합니다.이렇게 하면 이름이 유형에 직접 매핑되지 않는 모든 함수(예: CInt, CDbl, CSng 등)를 버릴 수도 있습니다.우리는 그들 대신에 다이렉트캐스트를 사용할 것입니다.

언급URL : https://stackoverflow.com/questions/2683847/cs-equivalent-to-vb-nets-directcast

반응형