Çevre: Visual Studio 2015 RTM. (Eski sürümleri denemedim.)
Son zamanlarda, Noda Time kodumdan bazılarının hatalarını ayıkladım ve yerel bir değişken NodaTime.Instant
( struct
Noda Time'daki merkezi türlerden biri), "Locals" ve "Watch" pencerelerini aldığımda fark ettim. ToString()
geçersiz kılma olarak görünmüyor . ToString()
İzleme penceresinde açıkça çağırırsam , uygun temsili görüyorum, ancak aksi takdirde sadece görüyorum:
variableName {NodaTime.Instant}
ki bu pek kullanışlı değil.
Ben sabit dize döndürmek için geçersiz kılma değiştirirseniz, dize olduğunu açıkça orada olduğunu toplayabildiğinde yüzden, ayıklayıcısında görüntülenen - bu sadece kendi "normal" durumda kullanmak istemiyor.
Bunu küçük bir demo uygulamasında yerel olarak çoğaltmaya karar verdim ve işte ne buldum. (Bu yazının erken bir versiyonunda DemoStruct
bir sınıf olduğunu ve DemoClass
hiç var olmadığını unutmayın - benim hatam, ama şimdi garip görünen bazı yorumları açıklıyor ...)
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();
}
}
Hata ayıklayıcıda, şimdi görüyorum:
demoClass {DemoClass}
demoStruct {Struct: Bar}
Ancak, Thread.Sleep
çağrıyı 1 saniyeden 900 ms'ye düşürürsem, hala kısa bir duraklama olur, ancak sonra Class: Foo
değer olarak görüyorum . Thread.Sleep
Çağrının ne kadar sürdüğü önemli değil DemoStruct.ToString()
, her zaman düzgün görüntüleniyor - ve hata ayıklayıcı, uyku tamamlanmadan önce değeri görüntüler. (Sanki Thread.Sleep
devre dışı gibi.)
Şimdi Instant.ToString()
Noda Time'da adil bir miktar iş var, ama kesinlikle bir saniye sürmez - bu yüzden muhtemelen hata ayıklayıcının bir ToString()
çağrıyı değerlendirmekten vazgeçmesine neden olan daha fazla koşul vardır . Ve elbette bu bir yapı.
Bir yığın sınırı olup olmadığını görmek için yinelenen denedim, ama durum böyle değil.
Öyleyse, VS'nin tam olarak değerlendirilmesini engelleyen şeyi nasıl çözebilirim Instant.ToString()
? Aşağıda belirtildiği gibi, DebuggerDisplayAttribute
yardımcı gibi görünüyor, ancak nedenini bilmeden , ihtiyaç duyduğumda ve ihtiyaç duymadığım zaman asla tamamen emin olmayacağım.
Güncelleme
Eğer kullanırsam DebuggerDisplayAttribute
işler değişir:
// For the sample code in the question...
[DebuggerDisplay("{ToString()}")]
public class DemoClass
bana verir:
demoClass Evaluation timed out
Oysa Noda Time'a uyguladığımda:
[DebuggerDisplay("{ToString()}")]
public struct Instant
basit bir test uygulaması bana doğru sonucu gösterir:
instant "1970-01-01T00:00:00Z"
Bu yüzden muhtemelen Noda Time'daki problem, zaman aşımlarından geçmese bile DebuggerDisplayAttribute
, zorlayan bir durumdur . (Bu, Instant.ToString
zaman aşımından kaçınmak için yeterince hızlı olan beklentim doğrultusunda olacaktır .)
Bu olabilir yeterince iyi bir çözüm olabilir - ama yine de böyle neler biliyorum ve Noda Zamanında bütün değişik değer türleri üzerinde niteliğini koymak zorunda kalmamak için sadece kodunu değiştirmek veya reddetmek için istiyorum.
Meraklı ve meraklı
Hata ayıklayıcının kafasını karıştıran ne varsa, sadece bazen karıştırır. En bir sınıf oluşturalım tutan bir Instant
ve kendi için kullanır ToString()
yöntemle:
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();
}
}
Şimdi görüyorum:
instant {NodaTime.Instant}
wrapper {1970-01-01T00:00:00Z}
Ancak, yorumlarda Eren'in önerisinde, InstantWrapper
bir yapı olarak değişirsem , şunu elde ederim:
instant {NodaTime.Instant}
wrapper {InstantWrapper}
O yüzden olabilir değerlendirmek Instant.ToString()
- bu kadar uzun başka bir kişinin çağrılan olarak ToString
bir sınıf içinde yöntemle .... Class / struct kısmı, sonucu elde etmek için hangi kodun yürütülmesi gerektiğine değil, görüntülenen değişkenin türüne göre önemli görünüyor.
Bunun başka bir örneği olarak, eğer kullanırsak:
object boxed = NodaConstants.UnixEpoch;
... sonra düzgün çalışıyor, doğru değeri gösteriyor. Renk karıştı beni.
DebuggerDisplayAttribute
biraz denemek için neden olur.