환경 : Visual Studio 2015 RTM. (이전 버전은 시도하지 않았습니다.)
최근에, 나는 일부 Noda Time 코드를 디버깅하고 있으며 , 지역 변수 유형 NodaTime.Instant
( struct
Noda Time 의 중심 유형 중 하나 ), "Locals"및 "Watch"창을 발견했습니다. ToString()
재정의 를 호출하지 않는 것 같습니다 . ToString()
조사 식 창에서 명시 적으로 호출 하면 적절한 표현이 표시되지만 그렇지 않으면 다음과 같이 표시됩니다.
variableName {NodaTime.Instant}
그다지 유용하지 않습니다.
상수 문자열을 반환하도록 재정의를 변경하면 문자열 이 디버거에 표시되므로 해당 문자열 이 분명히 있음을 알 수 있습니다. "정상"상태에서 사용하고 싶지 않습니다.
나는 이것을 작은 데모 앱에서 로컬로 재현하기로 결정했으며, 여기에 내가 생각해 낸 것이 있습니다. (이 게시물의 초기 버전 DemoStruct
에서는 수업이었고 DemoClass
전혀 존재하지 않았습니다-내 잘못이지만, 지금은 이상하게 보이는 몇 가지 의견을 설명합니다 ...)
using System;
using System.Diagnostics;
using System.Threading;
public struct DemoStruct
{
public string Name { get; }
public DemoStruct(string name)
{
Name = name;
}
public override string ToString()
{
Thread.Sleep(1000); // Vary this to see different results
return $"Struct: {Name}";
}
}
public class DemoClass
{
public string Name { get; }
public DemoClass(string name)
{
Name = name;
}
public override string ToString()
{
Thread.Sleep(1000); // Vary this to see different results
return $"Class: {Name}";
}
}
public class Program
{
static void Main()
{
var demoClass = new DemoClass("Foo");
var demoStruct = new DemoStruct("Bar");
Debugger.Break();
}
}
디버거에서 이제 볼 수 있습니다.
demoClass {DemoClass}
demoStruct {Struct: Bar}
그러나 Thread.Sleep
통화를 1 초에서 900ms로 줄이면 여전히 일시 정지가 발생하지만 Class: Foo
값으로 간주합니다. Thread.Sleep
호출 시간은 중요하지 않으며 DemoStruct.ToString()
항상 올바르게 표시되며 디버거는 절전 모드가 완료되기 전에 값을 표시합니다. ( Thread.Sleep
비활성화 된 것처럼 보입니다.)
이제 Instant.ToString()
Noda Time에서는 상당한 양의 작업을 수행하지만 확실히 1 초가 걸리지 않으므로 디버거가 ToString()
호출 평가를 포기하게하는 조건이 더 많이있을 수 있습니다 . 그리고 물론 그것은 구조입니다.
스택 제한인지 확인하기 위해 되풀이를 시도했지만 그럴 수는 없습니다.
그렇다면 VS가 완전히 평가하지 못하게하는 원인을 어떻게 해결할 수 Instant.ToString()
있습니까? 아래에 언급했듯이 DebuggerDisplayAttribute
도움이되는 것처럼 보이지만 이유 를 모르면 필요할 때와 필요하지 않을 때 완전히 확신 할 수는 없습니다.
최신 정보
를 사용 DebuggerDisplayAttribute
하면 상황이 변경됩니다.
// For the sample code in the question...
[DebuggerDisplay("{ToString()}")]
public class DemoClass
나에게 준다 :
demoClass Evaluation timed out
Noda Time에 신청할 때 :
[DebuggerDisplay("{ToString()}")]
public struct Instant
간단한 테스트 앱이 올바른 결과를 보여줍니다.
instant "1970-01-01T00:00:00Z"
그래서 아마 노다 시간의 문제는 어떤 조건입니다 DebuggerDisplayAttribute
수행 을 통해 힘 -이 시간 제한을 통해 강제하지 않더라도. (이것은 Instant.ToString
시간 초과를 피하기에 충분히 빠르다는 나의 기대와 일치 합니다.)
이 수 충분히 좋은 해결책이 될 수 -하지만, 난 여전히처럼 무슨 일이 일어나고 있는지 알고, 내가 노다 시간에 모든 다양한 값 형식에 속성을 넣어 것을 피하기 위해 단순히 코드를 변경할 수 있는지 여부하는 것입니다.
호기심과 호기심
디버거를 혼란스럽게 만드는 것은 때때로 혼란스럽게합니다. 의 클래스 만들어 보자 보유 을 Instant
하고 자신을 위해 그것을 사용하는 ToString()
방법 :
using NodaTime;
using System.Diagnostics;
public class InstantWrapper
{
private readonly Instant instant;
public InstantWrapper(Instant instant)
{
this.instant = instant;
}
public override string ToString() => instant.ToString();
}
public class Program
{
static void Main()
{
var instant = NodaConstants.UnixEpoch;
var wrapper = new InstantWrapper(instant);
Debugger.Break();
}
}
이제 나는보고 :
instant {NodaTime.Instant}
wrapper {1970-01-01T00:00:00Z}
그러나 Eren의 의견에 따르면 InstantWrapper
구조체로 변경 하면 다음과 같은 결과를 얻습니다.
instant {NodaTime.Instant}
wrapper {InstantWrapper}
따라서 클래스 내에서 다른 메소드에 의해 호출되는 한 평가할 수 있습니다 . 클래스 / 구조 부분은 결과를 얻기 위해 어떤 코드를 실행해야하는지가 아니라 표시되는 변수의 유형에 따라 중요해 보입니다.Instant.ToString()
ToString
이것의 또 다른 예로, 다음을 사용하면 :
object boxed = NodaConstants.UnixEpoch;
... 그런 다음 제대로 작동하여 올바른 값을 표시합니다. 혼란스러워
DebuggerDisplayAttribute
조금 더 열심히 시도 할 수도 있습니다.