पर्यावरण: विज़ुअल स्टूडियो 2015 आरटीएम। (मैंने पुराने संस्करणों की कोशिश नहीं की है।)
हाल ही में, मैं अपने कुछ Noda Time कोड डीबग कर रहा हूं , और मैंने देखा है कि जब मुझे स्थानीय प्रकार का NodaTime.Instant
( struct
Noda Time में केंद्रीय प्रकारों में से एक ) मिला है, तो "लोकल" और "वॉच" विंडो इसके 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()
नोदा टाइम में उचित मात्रा में काम किया जाता है, लेकिन यह निश्चित रूप से एक दूसरे को पूरा नहीं करता है - इसलिए संभवतः अधिक स्थितियां हैं जो डिबगर को ToString()
कॉल का मूल्यांकन करने का कारण बनाती हैं। और निश्चित रूप से यह वैसे भी एक संरचना है।
मैंने यह देखने की कोशिश की है कि क्या यह एक स्टैक सीमा है, लेकिन ऐसा प्रतीत नहीं होता है।
तो, मैं कैसे काम कर सकता हूं जो वीएस को पूरी तरह से मूल्यांकन करने से रोक रहा है 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"
तो संभवतः Noda Time में समस्या कुछ ऐसी स्थिति है जो 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}
हालांकि, टिप्पणियों में एरेन के सुझाव पर, अगर मैं InstantWrapper
एक संरचना बनने के लिए बदलूं, तो मुझे यह मिलेगा:
instant {NodaTime.Instant}
wrapper {InstantWrapper}
तो यह मूल्यांकन कर सकता है Instant.ToString()
- जब तक कि इसे किसी अन्य ToString
विधि द्वारा लागू किया जाता है ... जो कि एक वर्ग के भीतर है। वर्ग / संरचना वाला भाग प्रदर्शित होने वाले चर के आधार पर महत्वपूर्ण लगता है, न कि परिणाम प्राप्त करने के लिए किस कोड को निष्पादित करने की आवश्यकता होती है।
इसका एक और उदाहरण के रूप में, यदि हम उपयोग करते हैं:
object boxed = NodaConstants.UnixEpoch;
... तो यह ठीक काम करता है, सही मूल्य प्रदर्शित करता है। मुझे उलझन में रंग।
DebuggerDisplayAttribute
यह एक छोटे से कठिन प्रयास करने का कारण होगा।