পরিবেশ: ভিজ্যুয়াল স্টুডিও 2015 আরটিএম। (আমি পুরানো সংস্করণ চেষ্টা করিনি।)
সাম্প্রতিককালে, আমি আমার নোডা টাইম কোডটি কিছু ডিবাগ করেছি এবং আমি লক্ষ্য করেছি যে যখন আমি স্থানীয় ধরণের NodaTime.Instant( structনোডা সময়ের অন্যতম প্রধান কেন্দ্রীয় ) ভেরিয়েবল পেয়েছি , তখন "স্থানীয়" এবং "দেখুন" উইন্ডোজ এটির 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
আমি যখন নোডা সময় এটি প্রয়োগ করি:
[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}
যাইহোক, মন্তব্যগুলিতে ইরেনের পরামর্শে, আমি যদি InstantWrapperস্ট্রাক্ট হিসাবে পরিবর্তিত হই তবে আমি পাই:
instant {NodaTime.Instant}
wrapper {InstantWrapper}
সুতরাং এটি মূল্যায়ন করতে পারেInstant.ToString() - যতক্ষণ না এটি অন্য ToStringপদ্ধতি দ্বারা চালিত হয় ... যা কোনও শ্রেণীর মধ্যে থাকে। শ্রেণি / কাঠামোর অংশটি ভেরিয়েবলের ধরণের ভিত্তিতে গুরুত্বপূর্ণ বলে মনে হচ্ছে, ফলাফল পাওয়ার জন্য কোন কোডটি কার্যকর করা দরকার।
এর অন্য উদাহরণ হিসাবে, যদি আমরা ব্যবহার করি:
object boxed = NodaConstants.UnixEpoch;
... তাহলে এটি ঠিক কাজ করে, সঠিক মানটি প্রদর্শন করে। রঙিন আমাকে বিভ্রান্ত।
DebuggerDisplayAttributeএটি আরও কঠিন চেষ্টা করার কারণ হতে পারে ।