[c#] C # 또는 .NET에서 가장 이상한 경우는 무엇입니까? [닫은]

나는 몇 가지 코너 케이스와 뇌 맛보기를 수집하고 항상 더 많은 것을 듣고 싶습니다. 이 페이지는 실제로 C # 언어 비트와 밥을 다루지 만 핵심 .NET 항목도 흥미 롭습니다. 예를 들어, 여기 페이지에 없지만 믿을 수없는 것을 발견했습니다.

string x = new string(new char[0]);
string y = new string(new char[0]);
Console.WriteLine(object.ReferenceEquals(x, y));

False를 인쇄 할 것으로 예상됩니다-결국 “새”(참조 유형) 항상 새 개체를 생성합니까? C #과 CLI 모두에 대한 사양에 따라야합니다. 글쎄,이 특별한 경우에는 그렇지 않습니다. True를 인쇄하고 테스트 한 모든 버전의 프레임 워크에서 수행했습니다. (필자는 분명히 모노에서 시도하지 않았습니다 …)

분명히, 이것은 내가 찾고있는 종류의 예일뿐입니다-나는이 이상한 점에 대한 토론 / 설명을 특별히 찾지 않았습니다. (일반 문자열 인턴과 동일하지 않습니다. 특히 문자열 인턴은 생성자가 호출 될 때 일반적으로 발생하지 않습니다.) 실제로 비슷한 이상한 동작을 요구했습니다.

다른 보석이 숨어 있습니까?



답변

나는 당신에게 이것을 이전에 보여줬다 고 생각하지만, 나는 여기서 재미를 좋아합니다-이것은 추적하기 위해 약간의 디버깅이 필요했습니다! (원래 코드는 분명히 더 복잡하고 미묘했습니다 …)

    static void Foo<T>() where T : new()
    {
        T t = new T();
        Console.WriteLine(t.ToString()); // works fine
        Console.WriteLine(t.GetHashCode()); // works fine
        Console.WriteLine(t.Equals(t)); // works fine

        // so it looks like an object and smells like an object...

        // but this throws a NullReferenceException...
        Console.WriteLine(t.GetType());
    }

그래서 T는 …

답변 : 어떤 Nullable<T>– 등 int?. GetType ()을 제외한 모든 메서드는 재정의됩니다. 따라서 null을 호출하는 object.GetType () …을 호출하기 위해 객체로 캐스팅 (따라서 null로)됩니다.


업데이트 : 줄거리가 두껍게 … Ayende Rahien은 자신의 블로그 에서 비슷한 도전을 던졌지 만 where T : class, new():

private static void Main() {
    CanThisHappen<MyFunnyType>();
}

public static void CanThisHappen<T>() where T : class, new() {
    var instance = new T(); // new() on a ref-type; should be non-null, then
    Debug.Assert(instance != null, "How did we break the CLR?");
}

그러나 이길 수 있습니다! 원격과 같은 것들에 의해 사용 된 것과 같은 간접적 사용; 경고-다음은 순수한 악입니다 .

class MyFunnyProxyAttribute : ProxyAttribute {
    public override MarshalByRefObject CreateInstance(Type serverType) {
        return null;
    }
}
[MyFunnyProxy]
class MyFunnyType : ContextBoundObject { }

이를 사용하면 new()호출이 프록시 ( MyFunnyProxyAttribute)로 리디렉션되어을 반환합니다 null. 자 가서 눈을 씻으십시오!


답변

은행가의 반올림.

이것은 컴파일러 버그 나 오작동이 아니라 이상한 코너 케이스입니다 …

.Net Framework는 Banker ‘s Rounding으로 알려진 구성표 또는 반올림을 사용합니다.

은행원 반올림에서 0.5 숫자는 가장 가까운 짝수로 반올림되므로

Math.Round(-0.5) == 0
Math.Round(0.5) == 0
Math.Round(1.5) == 2
Math.Round(2.5) == 2
etc...

이로 인해 잘 알려진 Round-Half-Up 반올림을 기반으로 재무 계산에서 예기치 않은 버그가 발생할 수 있습니다.

Visual Basic에서도 마찬가지입니다.


답변

이 함수는 Rec(0)(디버거가 아닌)으로 호출되면 어떻게됩니까?

static void Rec(int i)
{
    Console.WriteLine(i);
    if (i < int.MaxValue)
    {
        Rec(i + 1);
    }
}

대답:

  • 32 비트 JIT에서는 StackOverflowException이 발생합니다.
  • 64 비트 JIT에서는 모든 숫자를 int.MaxValue에 인쇄해야합니다.

때문입니다 64 비트 JIT 컴파일러는 꼬리 호출 최적화를 적용 32 비트 JIT하지 않는 반면,.

불행히도 이것을 검증 할 64 비트 머신이 없지만 메소드는 테일 콜 최적화를위한 모든 조건을 충족합니다. 아무도 가지고 있지 않다면 나는 그것이 사실인지 알고 싶습니다.


답변

이것을 할당하십시오!


이것은 내가 파티에서 묻고 싶은 것입니다 (아마도 더 이상 초대받지 않는 이유 일 것입니다).

다음 코드를 컴파일 할 수 있습니까?

    public void Foo()
    {
        this = new Teaser();
    }

쉬운 속임수는 다음과 같습니다.

string cheat = @"
    public void Foo()
    {
        this = new Teaser();
    }
";

그러나 실제 해결책은 다음과 같습니다.

public struct Teaser
{
    public void Foo()
    {
        this = new Teaser();
    }
}

따라서 값 유형 (구조체)이 this변수를 재 할당 할 수 있다는 사실은 알지 못합니다 .


답변

몇 년 전, 충성도 프로그램을 진행할 때 고객에게 제공되는 포인트의 양에 문제가있었습니다. 이 문제는 double을 int로 캐스팅 / 변환하는 것과 관련이 있습니다.

아래 코드에서 :

double d = 13.6;

int i1 = Convert.ToInt32(d);
int i2 = (int)d;

i1 == i2 입니까?

i1! = i2로 밝혀졌습니다. 변환 및 캐스트 연산자에서 다른 반올림 정책으로 인해 실제 값은 다음과 같습니다.

i1 == 14
i2 == 13

항상 Math.Ceiling () 또는 Math.Floor () 또는 요구 사항을 충족하는 MidpointRounding을 사용하는 Math.Round를 호출하는 것이 좋습니다.

int i1 = Convert.ToInt32( Math.Ceiling(d) );
int i2 = (int) Math.Ceiling(d);


답변

열거 형 함수 과부하가 있어도 0을 정수로 만들어야합니다.

0을 열거 형에 매핑하는 C # 핵심 팀의 이론적 근거를 알고 있었지만 여전히 직교하지는 않습니다. Npgsql의 .

테스트 예 :

namespace Craft
{
    enum Symbol { Alpha = 1, Beta = 2, Gamma = 3, Delta = 4 };


   class Mate
    {
        static void Main(string[] args)
        {

            JustTest(Symbol.Alpha); // enum
            JustTest(0); // why enum
            JustTest((int)0); // why still enum

            int i = 0;

            JustTest(Convert.ToInt32(0)); // have to use Convert.ToInt32 to convince the compiler to make the call site use the object version

            JustTest(i); // it's ok from down here and below
            JustTest(1);
            JustTest("string");
            JustTest(Guid.NewGuid());
            JustTest(new DataTable());

            Console.ReadLine();
        }

        static void JustTest(Symbol a)
        {
            Console.WriteLine("Enum");
        }

        static void JustTest(object o)
        {
            Console.WriteLine("Object");
        }
    }
}


답변

이것은 내가 지금까지 본 것 중 가장 특이한 것 중 하나입니다 (물론 여기에서 제외하십시오!) :

public class Turtle<T> where T : Turtle<T>
{
}

그것은 당신이 그것을 선언 할 수는 있지만 실제 사용하지는 않습니다. 왜냐하면 그것은 항상 당신이 다른 클래스로 센터에있는 클래스를 포장하도록 요구하기 때문입니다.

[농담] 거북이가 끝까지 내려간 것 같아 … [/ 농담]