টুস্ট্রিং ওভাররাইডের মূল্যায়ন বন্ধ করার জন্য ভিজ্যুয়াল স্টুডিও ডিবাগারটি কী করে?


221

পরিবেশ: ভিজ্যুয়াল স্টুডিও 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;

... তাহলে এটি ঠিক কাজ করে, সঠিক মানটি প্রদর্শন করে। রঙিন আমাকে বিভ্রান্ত।


7
@ ভিএস ২০১৩ তে জন একই আচরণ (একটি অতিরিক্ত বার্তা সহ আমাকে সি # 6 স্টাফ সরিয়ে ফেলতে হয়েছিল): নাম ফাংশন মূল্যায়ন অক্ষম হয়েছে কারণ পূর্ববর্তী ফাংশন মূল্যায়নের সময়সীমা শেষ হয়ে গেছে। ফাংশন মূল্যায়ন পুনরায় সক্ষম করতে আপনাকে কার্যকর করতে হবে। স্ট্রিং
ভিসি 74

1
সি # 6.0 @ 3-14159265358979323846264
নীল

1
হতে পারে একটি DebuggerDisplayAttributeএটি আরও কঠিন চেষ্টা করার কারণ হতে পারে ।
Rawling

1
এটি পঞ্চম পয়েন্ট নীলভট্ট 40.वर्ड প্রেস.কম / ২০১৫/০ //১…/২০১৪ @ 3-14159265358979323846264 নতুন সি # 6.0 এর জন্য দেখুন
নীল

5
@ ডায়োমিডিসস্পাইনেলিস: আচ্ছা আমি এখানে এটি জিজ্ঞাসা করেছি যাতে ক) যে কেউ ভিএসএসের অভ্যন্তরের আগে একই জিনিস দেখেছেন বা জানেন তিনি উত্তর দিতে পারেন; খ) ভবিষ্যতে যে কেউ একই ইস্যুতে দৌড়াদৌড়ি করলে দ্রুত উত্তর পেতে পারে।
জন স্কিটি

উত্তর:


193

হালনাগাদ:

এই বাগটি ভিজ্যুয়াল স্টুডিও 2015 আপডেট 2 এ স্থির করা হয়েছে আমাকে আপডেট 2 বা তার পরে আপডেট ব্যবহার করে স্ট্রাক্ট মানগুলিতে টোস্ট্রিংয়ের মূল্যায়নে সমস্যা হয় কিনা তা আমাকে জানতে দিন।

আসল উত্তর:

আপনি ভিজ্যুয়াল স্টুডিও 2015 দিয়ে একটি পরিচিত বাগ / ডিজাইন সীমাবদ্ধতার মধ্যে চলেছেন এবং স্ট্রাক্ট প্রকারভেদে টসস্ট্রিংকে কল করছেন। ডিল করার সময় এটিও লক্ষ্য করা যায় System.DateTimeSpanSystem.DateTimeSpan.ToString()ভিজ্যুয়াল স্টুডিও 2013 এর সাথে মূল্যায়ন উইন্ডোতে কাজ করে তবে 2015 সালে সর্বদা কাজ করে না।

আপনি যদি নিম্ন স্তরের বিশদগুলিতে আগ্রহী হন তবে এখানে যা চলছে তা এখানে:

মূল্যায়ন করতে ToString, ডিবাগার যা করেন "ফাংশন মূল্যায়ন" হিসাবে পরিচিত। ব্যাপকভাবে সরল পদে, ডিবাগার বর্তমান থ্রেড ব্যতীত সমস্ত থ্রেড স্থগিত করে, বর্তমান থ্রেডের প্রসঙ্গে ToStringফাংশনে পরিবর্তন করে , একটি গোপন প্রহরী ব্রেকপয়েন্ট সেট করে, তারপরে প্রক্রিয়াটি চালিয়ে যাওয়ার অনুমতি দেয়। গার্ড ব্রেকপয়েন্টে আঘাত করা হলে, ডিবাগারটি প্রক্রিয়াটিকে তার আগের অবস্থায় ফিরিয়ে দেয় এবং ফাংশনের রিটার্ন মানটি উইন্ডোটি জনপ্রিয় করতে ব্যবহৃত হয়।

ল্যাম্বদা এক্সপ্রেশন সমর্থন করতে, আমাদের ভিজ্যুয়াল স্টুডিও 2015-এ সিএলআর এক্সপ্রেশন মূল্যায়ন সম্পূর্ণরূপে আবার লিখতে হয়েছিল a একটি উচ্চ স্তরে, বাস্তবায়নটি হ'ল:

  1. রোজলিন বিভিন্ন পরিদর্শন উইন্ডোতে মানগুলি প্রদর্শনের জন্য এক্সপ্রেশন / স্থানীয় ভেরিয়েবলের জন্য এমএসআইএল কোড উত্পন্ন করে।
  2. ডিবাগার ফলাফল পেতে আইএলকে ব্যাখ্যা করে।
  3. যদি কোনও "কল" নির্দেশাবলী থাকে তবে ডিবাগার উপরে বর্ণিত হিসাবে কোনও ফাংশন মূল্যায়ন কার্যকর করে।
  4. ডিবাগার / রোসলিন এই ফলাফলটি নেয় এবং এটি ব্যবহারকারীর দেখানো গাছের মতো দৃশ্যে ফর্ম্যাট করে।

আইএল কার্যকর করার কারণে, ডিবাগার সর্বদা "বাস্তব" এবং "জাল" মানের একটি জটিল মিশ্রণ নিয়ে কাজ করে। ডিবাগ হওয়ার প্রক্রিয়াটিতে আসল মানগুলি আসলে বিদ্যমান। জাল মানগুলি কেবল ডিবাগার প্রক্রিয়াতেই বিদ্যমান। যথাযথ স্ট্রাক্ট শব্দার্থক প্রয়োগ করতে, ডিবাগারকে আইএল স্ট্যাকের স্ট্রাক্ট মানটি চাপানোর সময় সর্বদা মানটির একটি অনুলিপি তৈরি করতে হবে। অনুলিপি করা মানটি আর "আসল" মান হয় না এবং এখন কেবল ডিবাগার প্রক্রিয়াতেই বিদ্যমান। এর অর্থ যদি পরবর্তীতে আমাদের ফাংশন মূল্যায়ন করা দরকার হয় তবে আমরা ToStringপ্রক্রিয়াতে মানটির অস্তিত্ব না থাকায় আমরা তা করতে পারি না। চেষ্টা করার জন্য এবং মানটি পেতে হলে আমাদের কার্যকর করা উচিত ulateToStringপদ্ধতি। যদিও আমরা কিছু জিনিস অনুকরণ করতে পারি তবে অনেকগুলি সীমাবদ্ধতা রয়েছে। উদাহরণস্বরূপ, আমরা নেটিভ কোড অনুকরণ করতে পারি না এবং আমরা "বাস্তব" প্রতিনিধি মানগুলিতে কলগুলি বা প্রতিবিম্ব মানগুলিতে কল কার্যকর করতে পারি না।

এই সমস্ত বিষয় মাথায় রেখে আপনি এখানে বিভিন্ন আচরণের কারণ বোধ করছেন:

  1. NodaTime.Instant.ToStringডিবাগারটি মূল্যায়ন করছে না -> এটি কারণ স্ট্রাক্ট ধরণের এবং উপরে বর্ণিত হিসাবে টবস্ট্রিংয়ের প্রয়োগটি ডিবাগার দ্বারা অনুকরণ করা যায় না।
  2. Thread.SleepToStringকোনও স্ট্রাক্টে ডাকা হলে শূন্য সময় লাগে বলে মনে হয় -> এমুলেটরটি কার্যকর হচ্ছে ToString। থ্রেড.স্লিপ একটি দেশীয় পদ্ধতি, তবে এমুলেটরটি এটি সম্পর্কে অবগত এবং কেবল কলটিকে উপেক্ষা করে। আমরা চেষ্টা করে ব্যবহারকারীর কাছে দেখানোর জন্য একটি মান পেতে পারি। এক বিলম্ব এই ক্ষেত্রে সহায়ক হবে না।
  3. DisplayAttibute("ToString()")কাজ করে। -> বিভ্রান্তিকর। শুধুমাত্র অন্তর্নিহিত কলিং মধ্যে পার্থক্য ToStringএবং DebuggerDisplayযে অন্তর্নিহিত কোন সময় আউট হয় ToString মূল্যায়ন সব অন্তর্নিহিত নিষ্ক্রিয় করা হবে ToStringযে টাইপ পরবর্তী ডিবাগ অধিবেশন পর্যন্ত জন্য মূল্যায়ন। আপনি সেই আচরণটি পর্যবেক্ষণ করছেন।

ডিজাইনের সমস্যা / বাগের ক্ষেত্রে, আমরা ভিজ্যুয়াল স্টুডিওর ভবিষ্যতে প্রকাশের ক্ষেত্রে এটি সমাধান করার পরিকল্পনা করছি।

আশা করি বিষয়গুলি পরিষ্কার হয়ে যায়। আপনার আরও প্রশ্ন থাকলে আমাকে জানান। :-)


1
ইনস্ট্যান্ট.টোস্ট্রিং কীভাবে কাজ করে তার কোনও ধারণা যদি বাস্তবায়নটি কেবল "স্ট্রিং আক্ষরিক ফিরে আসে"? দেখে মনে হচ্ছে কিছু জটিলতা এখনও অবহেলিত নেই :) আমি যাচাই করে দেখব যে আমি সত্যিই সেই আচরণটি পুনরুত্পাদন করতে পারি ...
জন স্কিইট

1
@ জন, আমি নিশ্চিত না আপনি কী জিজ্ঞাসা করছেন। সত্যিকারের ফাংশন মূল্যায়ন করার সময় ডিবাগার বাস্তবায়নের অজ্ঞেয় এবং এটি সর্বদা এটি প্রথমে চেষ্টা করে। ডিবাগার কেবলমাত্র কলটি অনুকরণ করার প্রয়োজন হলে বাস্তবায়ন সম্পর্কে চিন্তা করে - একটি স্ট্রিং আক্ষরিক প্রত্যাবর্তন সর্বাধিক সহজ ক্ষেত্রে অনুকরণ করা।
প্যাট্রিক নেলসন - এমএসএফটি

8
আদর্শভাবে আমরা চাই সিএলআর সবকিছু সম্পাদন করুক। এটি সবচেয়ে নির্ভুল এবং নির্ভরযোগ্য ফলাফল সরবরাহ করে। এজন্য আমরা টসস্ট্রিং কলগুলির জন্য প্রকৃত ফাংশন মূল্যায়ন করি। যখন এটি সম্ভব না হয়, আমরা কলটি অনুকরণে ফিরে যাই। তার অর্থ ডিবাগারটি পদ্ধতিটি সম্পাদনকারী সিএলআর হওয়ার ভান করে। স্পষ্টত যদি বাস্তবায়নটি <কোড> "হ্যালো" </code> ফেরত দেয় তবে এটি করা সহজ। যদি প্রয়োগটি পি-ইনভোক করে তবে এটি আরও কঠিন বা অসম্ভব।
প্যাট্রিক নেলসন - এমএসএফটি

3
@ টাজাচস, এমুলেটরটি সম্পূর্ণ একক থ্রেডযুক্ত। যদি innerResultনাল হিসাবে শুরু হয়, লুপ কখনই শেষ হবে না এবং শেষ পর্যন্ত মূল্যায়ন সময় শেষ হবে। প্রকৃতপক্ষে, মূল্যায়নগুলি কেবল ডিফল্টরূপে প্রক্রিয়াটির একক থ্রেডকে মঞ্জুরি দেয়, তাই আপনি যদি এমুলেটর ব্যবহার করেন বা না ব্যবহৃত হয় তবে আপনি একই আচরণ দেখতে পাবেন see
প্যাট্রিক নেলসন - এমএসএফটি

2
বিটিডাব্লু, যদি আপনি জানেন যে আপনার মূল্যায়নের জন্য একাধিক থ্রেডের প্রয়োজন হয়, তবে ডিবাগারকে দেখুন ifyনোটেফটফ্রসড্র্যাডডেপেন্ডেন্সি । এই পদ্ধতিটি কল করার জন্য মূল্যায়নের উল্লেখ করে একটি বার্তা দিয়ে মূল্যায়ন বাতিল করে দেওয়া হবে যা চালানোর জন্য সমস্ত থ্রেড প্রয়োজন এবং ডিবাগার এমন একটি বোতাম সরবরাহ করবে যা ব্যবহারকারী মূল্যায়ন করার জন্য চাপ দিতে পারে। অসুবিধাটি হ'ল মূল্যায়নের সময় অন্য থ্রেডগুলিতে আঘাত করা কোনও ব্রেকপয়েন্টগুলি উপেক্ষা করা হবে।
প্যাট্রিক নেলসন - এমএসএফটি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.