#if DEBUG বনাম শর্তসাপেক্ষ ("DEBUG")


432

কোন বৃহত প্রকল্পে কোনটি ব্যবহার করা ভাল এবং কেন:

#if DEBUG
    public void SetPrivateValue(int value)
    { ... }
#endif

অথবা

[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value)
{ ... }


2
আপনি
এটিও

ইউনিটি বিকাশকারীদের জন্য নোট: DEBUG অর্থ সম্পাদক বা উন্নয়ন বিল্ডগুলিতে। ফোরাম.িউন.টি.থ্যাডস/…
কেভিনভিক্টর

উত্তর:


578

এটি আপনি যা যাচ্ছেন তার উপর এটি নির্ভর করে:

  • #if DEBUG: এখানের কোডটি এমনকি প্রকাশের সময় আইএল পর্যন্ত পৌঁছাবে না।
  • [Conditional("DEBUG")]: এই কোডটি আইএল পৌঁছে যাবে, তবে কলার সংকলন করার সময় DEBUG সেট না করা পর্যন্ত পদ্ধতিতে কলগুলি বাদ দেওয়া হবে।

ব্যক্তিগতভাবে আমি উভয়ই পরিস্থিতির উপর নির্ভর করে ব্যবহার করি:

শর্তসাপেক্ষে ("ডিইবিইউজি") উদাহরণ: আমি এটি ব্যবহার করি যাতে রিলিজের পরে আমাকে আমার কোডটি ফিরে যেতে হবে না এবং ডিবাগিংয়ের সময় আমি নিশ্চিত হতে চাই যে আমি কোনও টাইপস তৈরি করিনি। এই ফাংশনটি চেক করে যে আমি কোনও আইনের নাম আমার আইএনটিফাইপ্রোটার্টি চেঞ্জড স্টাফগুলিতে ব্যবহার করার চেষ্টা করার সময় সঠিকভাবে টাইপ করেছি।

[Conditional("DEBUG")]
[DebuggerStepThrough]
protected void VerifyPropertyName(String propertyName)
{
    if (TypeDescriptor.GetProperties(this)[propertyName] == null)
        Debug.Fail(String.Format("Invalid property name. Type: {0}, Name: {1}",
            GetType(), propertyName));
}

আপনি যদি না #if DEBUGএকইভাবে সেই ফাংশনে প্রতিটি কল মোড়তে ইচ্ছুক না হন তবে আপনি সত্যিই এটি ব্যবহার করে কোনও ফাংশন তৈরি করতে চান না #if DEBUG:

#if DEBUG
    public void DoSomething() { }
#endif

    public void Foo()
    {
#if DEBUG
        DoSomething(); //This works, but looks FUGLY
#endif
    }

বনাম:

[Conditional("DEBUG")]
public void DoSomething() { }

public void Foo()
{
    DoSomething(); //Code compiles and is cleaner, DoSomething always
                   //exists, however this is only called during DEBUG.
}

#if DEBUG উদাহরণ: ডাব্লুসিএফ যোগাযোগের জন্য বিভিন্ন বাইন্ডিং সেটআপ করার চেষ্টা করার সময় আমি এটি ব্যবহার করি।

#if DEBUG
        public const String ENDPOINT = "Localhost";
#else
        public const String ENDPOINT = "BasicHttpBinding";
#endif

প্রথম উদাহরণে, কোডটি সমস্ত বিদ্যমান, তবে DEBUG চালু না হলে কেবল এড়ানো হবে। দ্বিতীয় উদাহরণে, ডিএনবিইউ সেট করা আছে কি না তার উপর নির্ভর করে কনট ওভারপয়েন্টটি "লোকালহোস্ট" বা "বেসিকএইচটিপিবাইন্ডিং" এ সেট করা আছে।


আপডেট: আমি একটি গুরুত্বপূর্ণ এবং কৌতুকপূর্ণ বিষয়টি স্পষ্ট করতে এই উত্তরটি আপডেট করছি। আপনি যদি ব্যবহারটি বেছে নেন ConditionalAttribute, মনে রাখবেন যে সংকলনের সময় কলগুলি বাদ দেওয়া হয়েছে, এবং রানটাইম নয় । এটাই:

MyLibrary.dll

[Conditional("DEBUG")]
public void A()
{
    Console.WriteLine("A");
    B();
}

[Conditional("DEBUG")]
public void B()
{
    Console.WriteLine("B");
}

গ্রন্থাগার মুক্তি মোড (অর্থাত কোনো ডিবাগ প্রতীক) বিরুদ্ধে কম্পাইল থাকে, তখন তা চিরকাল কল করতে হবে B()-এ গিয়ে A()বাদ দেওয়া, এমনকি যদি একটি কলে A()কারণ ডিবাগ সমাবেশ আহ্বান সংজ্ঞায়িত করা হয় অন্তর্ভুক্ত করা হয়।


13
ডেসোমথিংয়ের জন্য #if ডিবাগ-এ #if DEBUG- এর চারপাশে সমস্ত কলিং স্টেটমেন্ট থাকার দরকার নেই। আপনি হয় 1: কেবলমাত্র # ডসোমিংয়ের অভ্যন্তর ডিবাগ করতে পারেন, বা ডসোমথিংয়ের ফাঁকা সংজ্ঞা দিয়ে একটি # বানাবেন। তবুও আপনার মন্তব্যটি আমার পার্থক্যটি বুঝতে সাহায্য করেছে, তবে #if যদি আপনি প্রদর্শন করেছেন তবে DEBUG এর মতো কুৎসিত হওয়ার দরকার নেই।
অপিওরন

3
যদি আপনি এই বিষয়বস্তুকে সবেমাত্র #BBG করেন তবে আপনার কোডটি একটি নন-ডিবাগ বিল্ডে চলাকালীন JIT এখনও ফাংশনে একটি কল অন্তর্ভুক্ত করতে পারে। কন্ডিশনাল অ্যাট্রিবিউট ব্যবহার করা মানে জেআইটি কোনও ডি-ডিইউইউজি বিল্ড করার সময় কলসাইটটি আউটপুট করতে না জানে।
জেফ ইয়েটস

2
@ জেফইটস: আপনি যা লিখছেন তা আমি যেভাবে বর্ণনা করেছি তার চেয়ে আলাদা কীভাবে তা আমি দেখতে পাই না।
আমার

1
@ আফেরন যদি আপনার কেবল # আই ডিবাগে ফাংশন সামগ্রী থাকে তবে ফাংশন কলটি এখনও কল স্ট্যাকটিতে যুক্ত করা হয়, যদিও এটি সাধারণত খুব গুরুত্বপূর্ণ হয় না, ঘোষণাপত্র যোগ করে এবং #if এ ফাংশন কলটির অর্থ সংকলক হিসাবে আচরণ করে যদি ফাংশনটি বিদ্যমান না থাকে, সুতরাং আমার পদ্ধতিটি #if ব্যবহারের আরও "সঠিক" উপায়। যদিও উভয় পদ্ধতিই এমন ফলাফল দেয় যা সাধারণ ব্যবহারে একে অপরকে পৃথক করা যায়
মাইকেটি

5
কারও ভাবছেন, আইএল = অন্তর্বর্তী ভাষা - en.wikipedia.org/wiki/Common_Intermediate_Language
jbyrd

64

ভাল, এটি লক্ষণীয় যে তারা মোটেও একই জিনিসটি বোঝায় না।

যদি ডিইবিইউজি প্রতীকটি সংজ্ঞায়িত না করা হয়, তবে প্রথম ক্ষেত্রে SetPrivateValueনিজেকে বলা হবে না ... যদিও দ্বিতীয় ক্ষেত্রে এটি উপস্থিত থাকবে, তবে ডিইবিইউজি প্রতীক ছাড়াই সংকলিত যে কোনও কলকারী সেই কলগুলি বাদ দেবে।

কোড এবং তার সকল কলারের একই হন সমাবেশ এই পার্থক্য নেই কম গুরুত্বপূর্ণ - কিন্তু এটা যে প্রথম ক্ষেত্রে আপনি মানে এছাড়াও থাকতে হবে #if DEBUGপ্রায় কলিং পাশাপাশি কোড।

ব্যক্তিগতভাবে আমি দ্বিতীয় পদ্ধতির সুপারিশ করতাম - তবে আপনাকে তাদের মাথার মধ্যে পার্থক্য পরিষ্কার রাখতে হবে।


5
কলিং কোডের জন্য +1 এর সাথে # আইফোন বিবরণ থাকাও দরকার। যার অর্থ হল #if বিবৃতিগুলির একটি বিস্তার থাকবে ...
লুকাস বি

যদিও দ্বিতীয় বিকল্পটি (শর্তসাপেক্ষ বৈশিষ্ট্য) কিছু ক্ষেত্রে ভাল এবং ক্লিনার, এটি সংযোগ করার সময় একটি পদ্ধতি কলটি সমাবেশ থেকে ছিনিয়ে নেওয়া হবে (উদাহরণস্বরূপ নামকরণের কনভেনশন দ্বারা) যোগাযোগ করার প্রয়োজন হতে পারে।
লিজেরজিক-অ্যাসিড

45

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

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


4
আমি তোমার সাথে জিমির সাথে পুরোপুরি একমত আপনি যদি ডিআই ব্যবহার করে থাকেন এবং আপনার পরীক্ষাগুলির জন্য উপহাস করছেন, তবে #if debugআপনার কোডে আপনার কেন বা অনুরূপ কোনও নির্মাণের প্রয়োজন হবে ?
রিচার্ড এভ

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

4
কেবল পরীক্ষার জন্য নয়, আমরা প্রায়শই নিজের কাছে একটি ডিফল্ট প্রাপক ইমেল সেট করার মতো জিনিস করি, ডিবাগ তৈরি করে, #if DEBUGযাতে ব্যবহার করি যাতে প্রক্রিয়াটির অংশ হিসাবে ইমেলগুলি প্রেরণ করতে হবে এমন কোনও সিস্টেমের পরীক্ষা করার সময় আমরা অন্যের সাথে দুর্ঘটনাক্রমে স্প্যাম না করি। কখনও কখনও এই কাজের সঠিক সরঞ্জামসমূহ :)
কোডিং হয়ে গেছে

6
আমি সাধারণত আপনার সাথে একমত হব তবে আপনি যদি এমন পরিস্থিতিতে থাকেন যেখানে পারফরম্যান্স সর্বজনীন হয় তবে আপনি বহিরাগত লগিং এবং ব্যবহারকারীর আউটপুট সহ কোডটিকে বিশৃঙ্খলা করতে চান না, তবে আমি 100% সম্মতি দিই যে সেগুলি কখনও পরিবর্তনের জন্য ব্যবহার করা উচিত নয় মৌলিক আচরণ
মাইকটি

5
-1 এগুলির কোনওটিই ব্যবহার করে কোনও ভুল নেই। দাবি ইউনিট পরীক্ষা এবং ডিআই কোনওরকম কোনও পণ্যটির একটি ডিবাগ সক্ষম বিল্ডকে প্রতিস্থাপন করে নিখুঁত।
টেড বিঘাম

15

এটি এক হিসাবে দরকারী হতে পারে:

if (Debugger.IsAttached)
{
...
}

1
ব্যক্তিগতভাবে, আমি দেখতে পাচ্ছি না যে এটি অন্যান্য 2 টি বিকল্পের তুলনায় কীভাবে কার্যকর হতে পারে। এটি গ্যারান্টি দেয় যে পুরো ব্লকটি সংকলিত হয়েছে, এবং Debugger.IsAttachedরিলিজ বিল্ডগুলিতে এমনকি রানটাইমে কল করা উচিত।
জয়

9

প্রথম উদাহরণ দিয়ে, SetPrivateValueBuild এ থাকবে না যদি DEBUGসংজ্ঞায়িত করা হয় না, দ্বিতীয় উদাহরণ, কল করার SetPrivateValueবিল্ড মধ্যে উপস্থিত না যদি DEBUGসংজ্ঞায়িত করা হয় না।

প্রথম উদাহরণ দিয়ে, আপনি কোনো কল মোড়ানো করতে হবে SetPrivateValueসঙ্গে #if DEBUGহিসাবে ভাল।

দ্বিতীয় উদাহরণ সহ, কলগুলি SetPrivateValueবাদ দেওয়া হবে, তবে সচেতন থাকুন যে SetPrivateValueনিজে থেকে এখনও সংকলিত হবে। আপনি যদি কোনও লাইব্রেরি তৈরি করছেন তবে এটি কার্যকর, সুতরাং আপনার লাইব্রেরির উল্লেখকারী অ্যাপ্লিকেশনটি এখনও আপনার ফাংশনটি ব্যবহার করতে পারে (যদি শর্তটি পূরণ হয়)।

আপনি যদি কলগুলি বাদ দিতে এবং কলির স্থান সংরক্ষণ করতে চান তবে আপনি দুটি কৌশলগুলির সংমিশ্রণটি ব্যবহার করতে পারেন:

[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value){
    #if DEBUG
    // method body here
    #endif
}

@ পি ড্যাডি: #if DEBUGচারপাশে মোড়ানো Conditional("DEBUG")এই ফাংশনটির কলগুলি সরিয়ে দেয় না, এটি কেবলমাত্র আইএল থেকে ফাংশনটি পুরোপুরি সরিয়ে দেয়, সুতরাং আপনার এখনও উপস্থিত নেই এমন ফাংশনে কল রয়েছে (সংকলন ত্রুটি)।
আমার

1
কোডটি প্রকাশের ক্ষেত্রে না থাকতে চাইলে "#if DEBUG" তে পদ্ধতি বডিটি আবদ্ধ করা উচিত, সম্ভবত "# লেস" স্টাব (একটি থ্রো বা ডামি রিটার্ন মান সহ) ব্যবহার করা উচিত এবং প্রস্তাবিত বৈশিষ্ট্যটি ব্যবহার করা উচিত কলকারীরা কল দিয়ে বিরক্ত করবেন না? এটি উভয় বিশ্বের সেরা মনে হবে।
সুপারক্যাট

@ মাইমারিয়ান, @ সুপের্যাট: হ্যাঁ, আপনি উভয়ই ঠিক আছেন। আমার ভুল. সুপার ক্যাট এর পরামর্শ অনুযায়ী আমি সম্পাদনা করব।
পি বাবা

5

আসুন ধরে নেওয়া যাক আপনার কোডেও একটি #elseবিবৃতি ছিল যা জোন স্কিটের একটি বিষয়কে সম্বোধন করে একটি নাল স্টাব ফাংশনকে সংজ্ঞায়িত করেছে। দুজনের মধ্যে দ্বিতীয় গুরুত্বপূর্ণ পার্থক্য রয়েছে।

মনে করুন ডিএলএলে #if DEBUGবা Conditionalফাংশনটি বিদ্যমান রয়েছে যা আপনার মূল প্রকল্পের নির্বাহযোগ্য দ্বারা রেফারেন্স করা হয়েছে। ব্যবহার করে #if, শর্তসাপেক্ষের মূল্যায়ন লাইব্রেরির সংকলন সেটিংসের সাথে সম্পাদিত হবে। Conditionalঅ্যাট্রিবিউটটি ব্যবহার করে , শর্তাধীনের মূল্যায়ন চালকের সংকলন সেটিংসের সাথে সম্পাদিত হবে।


2

কাস্টম ব্যবহার করে নেটওয়ার্ক ট্র্যাফিক লগ করতে আমার একটি এসওএপি ওয়েব সার্ভিস এক্সটেনশন রয়েছে [TraceExtension]। আমি এটি কেবলমাত্র ডিবাগ বিল্ডগুলির জন্য ব্যবহার করি এবং রিলিজ বিল্ডগুলি বাদ দেয় । রিলিজ বিল্ডস থেকে এটি মুছে #if DEBUGফেলাতে [TraceExtension]অ্যাট্রিবিউটটি মোড়ানোর জন্য ব্যবহার করুন ।

#if DEBUG
[TraceExtension]
#endif
[System.Web.Service.Protocols.SoapDocumentMethodAttribute( ... )]
[ more attributes ...]
public DatabaseResponse[] GetDatabaseResponse( ...) 
{
    object[] results = this.Invoke("GetDatabaseResponse",new object[] {
          ... parmeters}};
}

#if DEBUG
[TraceExtension]
#endif
public System.IAsyncResult BeginGetDatabaseResponse(...)

#if DEBUG
[TraceExtension]
#endif
public DatabaseResponse[] EndGetDatabaseResponse(...)

0

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

static class Program
{

    #region Private variable
    static readonly bool IsDebugMode = false;
    #endregion Private variable

    #region Constrcutors
    static Program()
    {
 #if DEBUG
        IsDebugMode = true;
 #endif
    }
    #endregion

    #region Main

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static void Main(string[] args)
    {

        if (IsDebugMode)
        {
            MyService myService = new MyService(args);
            myService.OnDebug();             
        }
        else
        {
            ServiceBase[] services = new ServiceBase[] { new MyService (args) };
            services.Run(args);
        }
    }

    #endregion Main        
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.