ব্যতিক্রমী সুরক্ষার জন্য "স্কোপড আচরণ" পাওয়ার উপায় হিসাবে আইডিজেসপোজেবল এবং "ব্যবহার" করা কি আপত্তিজনক?


111

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

সি # তে, আমি প্রায়শই করতে চাই

class FrobbleManager
{
    ...

    private void FiddleTheFrobble()
    {
        this.Frobble.Unlock();
        Foo();                  // Can throw
        this.Frobble.Fiddle();  // Can throw
        Bar();                  // Can throw
        this.Frobble.Lock();
    }
}

যা এইভাবে করা প্রয়োজন

private void FiddleTheFrobble()
{
    this.Frobble.Unlock();

    try
    {            
        Foo();                  // Can throw
        this.Frobble.Fiddle();  // Can throw
        Bar();                  // Can throw
    }
    finally
    {
        this.Frobble.Lock();
    }
}

আমি গ্যারান্টি করতে চান তাহলে Frobbleরাষ্ট্র যখন FiddleTheFrobbleআয়। কোডটি আরও ভাল লাগবে

private void FiddleTheFrobble()
{
    using (var janitor = new FrobbleJanitor(this.Frobble))
    {            
        Foo();                  // Can throw
        this.Frobble.Fiddle();  // Can throw
        Bar();                  // Can throw
    }
}

মোটামুটি মত FrobbleJanitorদেখতে যেখানে

class FrobbleJanitor : IDisposable
{
    private Frobble frobble;

    public FrobbleJanitor(Frobble frobble)
    {
        this.frobble = frobble;
        this.frobble.Unlock();
    }

    public void Dispose()
    {
        this.frobble.Lock();
    }
}

এবং এটিই আমি এটি করতে চাই। এখন বাস্তবে, আপ ক্যাচ যেহেতু আমি চাই ব্যবহারের প্রয়োজন যে FrobbleJanitorব্যবহার করা হয় সঙ্গে using । আমি এটি একটি কোড পর্যালোচনা ইস্যু বিবেচনা করতে পারে, কিন্তু কিছু আমাকে কড়া নাড়ছে।

প্রশ্ন: উপরেরগুলি আপত্তিজনক ব্যবহার হিসাবে বিবেচিত হবে usingএবং IDisposable?


23
শ্রেণি এবং পদ্ধতির নামের জন্য একা :-)। ভাল, ন্যায্য, এবং আসল প্রশ্ন।
জোয়

2
@ জোহানেস: হ্যাঁ, আমি দেখতে পাচ্ছি কেন - বেশিরভাগ লোকেরা কেবল তাদের ঝাঁকুনির ঝাঁকুনি খায় তবে আমাকে অবশ্যই এর বিরুদ্ধে প্রতিবাদ করতে হবে। ;-) এবং, যাইহোক, আপনার নামের মিলের জন্য +1।
জোহান জেরেল

সম্ভবত আপনি লক (এটি) {..} সুযোগটি ব্যবহার করতে পারেন এই উদাহরণে একই ফলাফলটি অর্জন করতে?

1
@ ওɔɯǝɹ: আপনি বিভিন্ন থ্রেড থেকে কিছুতে এক সাথে অ্যাক্সেস রোধ করতে লক () ব্যবহার করেন। আমি যে দৃশ্যের বর্ণনা দিয়েছি তার কিছুই করার নেই।
জোহান গেরেল

1
সি # এর :) পরবর্তী সংস্করণ কোন Finalizer সঙ্গে IScopeable
জন Raynor ও

উত্তর:


32

অগত্যা আমি তা মনে করি না। IDisposable টেকনিক্যালি হয় কিছু অ-পরিচালিত সম্পদ আছে, কিন্তু তারপর নির্দেশ ব্যবহার করে শুধু একটি সাধারণ প্যাটার্ন বাস্তবায়নের একটি ঝরঝরে উপায় জন্য ব্যবহার করা যেতে বোঝানো try .. finally { dispose }

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

এটিকে আরও দূরে ঠেলে আপনাকে সম্ভবত IDisposable এর উপরে অন্য একটি ইন্টারফেস আটকে রাখা উচিত, অন্য বিকাশকারীদের ব্যাখ্যা করে কেন সেই ইন্টারফেসটি আইডেসपोজযোগ্য বোঝায়।

এটি করার জন্য প্রচুর অন্যান্য বিকল্প রয়েছে তবে শেষ পর্যন্ত, আমি এর মতো ঝরঝরে এমন কোনও বিষয় ভাবতে পারি না, তাই এর জন্য যান!


2
আমি বিশ্বাস করি এটি পাশাপাশি "ব্যবহার" করার একটি শৈল্পিক ব্যবহার। আমি মনে করি যে সামিক জ্যাকের পোস্ট এরিক গোনারসনের একটি মন্তব্যে লিঙ্ক করেছে, "ব্যবহার" এর এই বাস্তবায়নটিকে বৈধ করেছে। আমি এটিতে আন্দ্রেস এবং এরিক উভয় থেকেই তৈরি দুর্দান্ত পয়েন্টগুলি দেখতে পাচ্ছি।
IAbstract

1
আমি এরিক গোনারসনের সাথে এই সম্পর্কে কিছুক্ষণ আগে কথা বলেছিলাম এবং তাঁর মতে এটি সি # ডিজাইন দলের উদ্দেশ্য ছিল যে ব্যবহারগুলি স্কোপগুলি বোঝায়। প্রকৃতপক্ষে, তিনি পোস্ট করেছেন যে তারা লক স্টেটমেন্টের আগে ব্যবহার করে ডিজাইন করেছিল, এমনকি কোনও লক স্টেটমেন্টও নাও থাকতে পারে। এটি একটি ব্যবহার ব্লক ডাব্লু / একটি মনিটরের কল বা কিছু ছিল। আপডেট: ঠিক বুঝতে পেরেছি যে পরবর্তী উত্তরটি এরিক লিপার্ট যিনি ভাষা দলে আছেন। ;) সম্ভবত সি # টিম নিজেও এ সম্পর্কে পুরোপুরি একমত নয়? ডাব্লু / গোনারসন আমার আলোচনার প্রসঙ্গটি ছিল টাইমলড ক্লাস: বিট.লি
হ্যাকড

2
@ হ্যাকড - মজাদার এটি নয়; আপনার মন্তব্য সম্পূর্ণ আমার বক্তব্য প্রমাণ করে; আপনি দলে একজনের সাথে কথা বলেছিলেন এবং তিনি তার পক্ষে ছিলেন; তারপরে নীচে এরিক লিপার্টকে দেখানো, একই দল থেকে একমত নয়। আমার দৃষ্টিকোণ থেকে; সি # এমন একটি কীওয়ার্ড সরবরাহ করে যা একটি ইন্টারফেস শোষণ করে এবং এমন একটি দুর্দান্ত বর্ণন কোড প্যাটার্ন দেয় যা এতগুলি পরিস্থিতিতে কাজ করে works যদি আমরা এটির অপব্যবহার না করার কথা না মনে করি, তবে সি # কে এটি প্রয়োগের জন্য অন্য কোনও উপায় খুঁজে পাওয়া উচিত। যে কোনও উপায়ে, ডিজাইনারদের সম্ভবত এখানে একটি পরপর তাদের হাঁসগুলি পাওয়া দরকার! এর মধ্যে: using(Html.BeginForm())স্যার? স্যার করলে কিছু মনে করবেন না! :)
আন্দ্রেস জোলটান

71

আমি এটিকে ব্যবহারের বিবৃতিটির অপব্যবহার বলে মনে করি। আমি সচেতন যে আমি এই পদে সংখ্যালঘুতে আছি।

আমি এটিকে তিনটি কারণে অপব্যবহার হিসাবে বিবেচনা করি।

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

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

এবং তৃতীয়ত, আপনার প্রোগ্রামের ক্রিয়াগুলি তার রাষ্ট্র দ্বারা নির্ধারিত হয়; রাষ্ট্রের যত্ন সহকারে কারসাজির প্রয়োজনীয়তা হ'ল আমরা কেন এই কথোপকথনটি প্রথম স্থানে করছি। আসুন আমরা কীভাবে আপনার মূল প্রোগ্রামটি বিশ্লেষণ করতে পারি তা বিবেচনা করুন।

আপনি কি আমার অফিসে কোনও কোড পর্যালোচনায় এনেছিলেন, আমি প্রথম প্রশ্নটি জিজ্ঞাসা করব "যদি কোনও ব্যতিক্রম ছুঁড়ে দেওয়া হয় তবে ফ্রোবলকে লক করা কি সত্যিই সঠিক?" আপনার প্রোগ্রাম থেকে এটা স্পষ্টতই স্পষ্ট যে এই জিনিস আক্রমণাত্মকভাবে frobble আবার লক করে যাই ঘটুক না কেন। এটা কি সঠিক? একটি ব্যতিক্রম নিক্ষেপ করা হয়েছে। প্রোগ্রামটি অজানা অবস্থায় রয়েছে। আমরা জানি না যে ফু, ফিডল বা বার ছুড়েছিল, তারা কেন ছুঁড়েছিল, বা অন্য রাজ্যে কী রূপান্তর করেছিল যা পরিষ্কার হয়নি। আপনি কি আমাকে বোঝাতে পারেন যে সেই ভয়াবহ পরিস্থিতিতে পুনরায় লক করা সর্বদা সঠিক জিনিস?

হতে পারে, সম্ভবত এটি না। আমার বক্তব্যটি হ'ল, কোডটি যেমন এটি লেখা হয়েছিল ঠিক তেমনই, কোড পর্যালোচক প্রশ্ন জিজ্ঞাসা করতে জানে । "ব্যবহার" ব্যবহার করে এমন কোড সহ, আমি প্রশ্ন জিজ্ঞাসা করতে জানি না; আমি ধরে নিয়েছি যে "ব্যবহার" ব্লকটি কোনও সংস্থান বরাদ্দ করে, কিছুটা জন্য এটি ব্যবহার করে, এবং সম্পন্ন হওয়ার পরে বিনয়ের সাথে তা নিষ্পত্তি করে না, "ব্যবহার" ব্লকের সমাপনী ব্রেসটি আমার প্রোগ্রামের স্থিতিকে একচ্ছত্র ব্যর্থতায় পরিণত করে যখন নির্বিচারে অনেকগুলি প্রোগ্রামের রাষ্ট্রের ধারাবাহিকতার শর্তগুলি লঙ্ঘন করা হয়েছে।

অর্থ ব্যবহারের জন্য "ব্যবহার" ব্লক ব্যবহার এই প্রোগ্রামটিকে খণ্ডিত করে তোলে:

}

অত্যন্ত অর্থবহ। আমি যখন একক ঘনিষ্ঠ বন্ধনীটি দেখি তখনই আমি তাৎক্ষণিকভাবে মনে করি না "এই ধনুর্বন্ধনের পার্শ্ব প্রতিক্রিয়া রয়েছে যা আমার প্রোগ্রামের বিশ্বব্যাপী অবস্থার সুদূরপ্রসারী প্রভাব ফেলেছে"। কিন্তু আপনি যখন এইরকম "ব্যবহার" করার অপব্যবহার করেন, হঠাৎ করে তা হয়ে যায়।

দ্বিতীয় জিনিসটি আমি জিজ্ঞাসা করব যদি আমি আপনার মূল কোডটি দেখেছি তবে "আনলক করার পরে ব্যতিক্রম ছুঁড়ে দেওয়া হলেও চেষ্টাটি প্রবেশ করার আগে কী ঘটে?" আপনি যদি একটি অপ্টিমাইটিজড অ্যাসেমব্লি চালাচ্ছেন তবে এই সংকলকটি চেষ্টা করার আগে কোনও অনি-নির্দেশ নির্দেশিকা সন্নিবেশ করিয়েছে এবং কোনও থ্রেড অ্যাওর্ট ব্যতিক্রমের জন্য কোনও বিকল্প নেই। এটি বিরল, তবে এটি বাস্তব জীবনে ঘটে, বিশেষত ওয়েব সার্ভারগুলিতে। সেক্ষেত্রে আনলকটি ঘটে তবে লকটি কখনই ঘটে না, কারণ ব্যতিক্রমটি চেষ্টা করার আগে ছুঁড়ে দেওয়া হয়েছিল। এটি সম্পূর্ণরূপে সম্ভব যে এই কোডটি এই সমস্যায় ঝুঁকিপূর্ণ এবং আসলে লেখা উচিত

bool needsLock = false;
try
{
    // must be carefully written so that needsLock is set
    // if and only if the unlock happened:

    this.Frobble.AtomicUnlock(ref needsLock);
    blah blah blah
}
finally
{
    if (needsLock) this.Frobble.Lock();
}

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


18
যদিও আমি প্রশ্নের উত্তর অন্যভাবে দেব, আমি মনে করি এটি একটি সুস্পষ্ট যুক্তিযুক্ত পোস্ট। যাইহোক, আমি আপনার দাবিটি নিয়ে ইস্যুটি গ্রহণ করি usingযা সঠিকতা ইস্যু না করে শালীনতা। আমি বিশ্বাস করি যে রিসোর্স লিকগুলি নির্ভুলতার সমস্যা, যদিও প্রায়শই এগুলি পর্যাপ্ত পরিমাণে যে তারা উচ্চ-অগ্রাধিকারের বাগ নয়। সুতরাং, usingব্লকগুলি ইতিমধ্যে প্রোগ্রামের স্থিতিতে প্রভাব ফেলেছে এবং তারা যা প্রতিরোধ করে তা কেবলমাত্র অন্যান্য প্রক্রিয়াতে "অসুবিধা" নয়, সম্ভবত একটি ভাঙ্গা পরিবেশ। এটি বলার অপেক্ষা রাখে না যে প্রশ্নের দ্বারা আরোপিত বিভিন্ন ধরণের শব্দার্থক প্রভাবটিও উপযুক্ত।
কেভিবি

13
রিসোর্স ফাঁস হ'ল শুদ্ধতার সমস্যা। কিন্তু "ব্যবহার" ব্যবহার করতে ব্যর্থতা সংস্থানটি ফাঁস করে না; ফাইনালাইজারটি চালিত হলে সংস্থান শেষ পর্যন্ত পরিষ্কার হয়ে যাবে। ক্লিনআপটি আপনার পছন্দ মতো আক্রমণাত্মক এবং সময়োপযোগী নাও হতে পারে তবে এটি হবে।
এরিক লিপার্ট

7
বিস্ময়কর পোস্ট, এখানে আমার দুটি সেন্ট :) আমি সন্দেহ করি অনেকটা "অপব্যবহার" usingহ'ল কারণ এটি সি # তে একজন দরিদ্র ব্যক্তির দিক ভিত্তিক তাঁতী। বিকাশকারী সত্যিই যা চান তা হ'ল গ্যারান্টি দেওয়ার একটি উপায় যে কোনও কোডের অনুলিপি ছাড়াই কোনও ব্লকের শেষে চলবে common সি # আজ এওপি সমর্থন করে না (মার্শালবিআরআইফফজেক্ট ও পোস্টশার্প প্রতিরোধ না করে)। তবে সংযোজনকারীর ব্যবহারের বিবৃতিতে রূপান্তরটি ডিটারমিনিস্টিক রিসোর্স নিষ্পত্তি সংক্রান্ত শব্দার্থকে পুনরায় পরিকল্পনা করে সহজ এওপি অর্জন সম্ভব করে। একটি ভাল অনুশীলন না হলেও এটি পাস করার জন্য মাঝে মাঝে আকর্ষণীয় হয় .....
এল বুশকিন

11
আমি সাধারণত আপনার অবস্থানের সাথে একমত হয়েছি এমন কিছু ক্ষেত্রে রয়েছে যেখানে পুনঃ-পরিকল্পনা করার সুবিধাটি ছেড়ে দেওয়া usingখুব আকর্ষণীয়। আমি সবচেয়ে ভাল উদাহরণটি মনে করতে পারি কোডের সময়গুলি ট্র্যাক করা এবং প্রতিবেদন করা: using( TimingTrace.Start("MyMethod") ) { /* code */ } আবার, এটি এওপি - Start()ব্লকটি শুরুর আগে শুরুর সময়টি Dispose()ক্যাপচার করে, শেষ সময়টি ক্যাপচার করে এবং ক্রিয়াকলাপটি লগ করে। এটি প্রোগ্রামের স্থিতি পরিবর্তন করে না এবং ব্যতিক্রমগুলিতে অজ্ঞেয়বাদী। এটি আকর্ষণীয় কারণ এটি নদীর গভীরতানির্ণয়কে কিছুটা এড়িয়ে চলে এবং একটি ধরণ হিসাবে এটি ঘন ঘন ব্যবহার বিভ্রান্তিকর শব্দার্থবিজ্ঞান প্রশমন করে।
এল বুশকিন

6
মজার, আমি সর্বদা RAII সমর্থন করার উপায় হিসাবে ব্যবহার করার কথা ভেবেছিলাম। লকটিকে এক ধরণের সংস্থান হিসাবে বিবেচনা করা আমার পক্ষে যুক্তিসঙ্গত স্বজ্ঞাত বলে মনে হয়।
ব্রায়ান

27

আপনি যদি কিছু পরিষ্কার, স্কোপড কোড চান, তবে আপনি ল্যাম্বডাস, লাও ব্যবহার করতে পারেন

myFribble.SafeExecute(() =>
    {
        myFribble.DangerDanger();
        myFribble.LiveOnTheEdge();
    });

যেখানে .SafeExecute(Action fribbleAction)পদ্ধতিটি try- catch- finallyব্লককে মোড়া করে ।


এই উদাহরণে, আপনি এন্ট্রি রাষ্ট্রটি মিস করেছেন। তদ্ব্যতীত, নিশ্চিত করুন যে আপনি মোড়ানো চেষ্টা / পরিশেষে, কিন্তু আপনি কল না পরিশেষে কিছু, তাই ল্যামডা কিছু ছোঁড়ার আপনি কি কোন ধারণা রাষ্ট্র আপনি আছেন থাকে।
জোহান Gerell

1
আহ! ঠিক আছে, আমি অনুমান করি আপনার অর্থ SafeExecuteহ'ল এমন একটি Fribbleপদ্ধতি যা কল করে Unlock()এবং Lock()মোড়ানো চেষ্টা / শেষ অবধি। আমার ক্ষমাপ্রার্থী তখন। আমি অবিলম্বে SafeExecuteজেনেরিক এক্সটেনশন পদ্ধতি হিসাবে দেখেছি এবং তাই প্রবেশ এবং প্রস্থান স্থিতির অভাবের কথা উল্লেখ করেছি। আমার খারাপ।
জোহান জেরেল

1
এই apporach সঙ্গে খুব সাবধান হন। বন্দী স্থানীয়দের ক্ষেত্রে কিছু বিপজ্জনক সূক্ষ্ম অযৌক্তিক জীবনকাল বাড়ানো হতে পারে!
জেসন

4
Yuk। চূড়ান্ত চেষ্টা / ধরা / শেষ পর্যন্ত কেন? অন্যদের পড়ার জন্য আপনার কোডকে আড়াল করে তোলে।
ফ্র্যাঙ্ক শোয়েটারম্যান

2
@ ইউক্কি ফ্র্যাঙ্ক: কোনও কিছু "আড়াল" করা আমার ধারণা নয় , এটি ছিল প্রশ্নকারীদের অনুরোধ। :- পি ... এটি বলেছিল, অনুরোধটি শেষ পর্যন্ত "নিজেকে পুনরাবৃত্তি করবেন না" এর একটি বিষয়। আপনার কাছে এমন অনেক পদ্ধতি থাকতে পারে যার জন্য পরিষ্কারভাবে কিছু অর্জন / প্রকাশের জন্য একই বয়লারপ্লেট "ফ্রেম" দরকার এবং আপনি কলারের উপরে এটি চাপিয়ে দিতে চান না (এনক্যাপসুলেশন সম্পর্কে ভাবেন)। এছাড়াও যে কেউ কী কীভাবে যথেষ্ট যোগাযোগ করতে পারে সে জন্য আরও পরিষ্কারভাবে .SafeExecute (...) এর মতো পদ্ধতির নাম রাখতে পারে।
হার্জমিস্টার

24

সি # ল্যাঙ্গুয়েজ ডিজাইনের দলে ছিলেন এরিক গোনারসন, একই প্রশ্নের উত্তরটি বেশিরভাগ ক্ষেত্রে দিয়েছেন :

ডগ জিজ্ঞাসা:

পুনরায়: সময়সীমা সহ একটি লক স্টেটমেন্ট ...

আমি বিভিন্ন পদ্ধতিতে সাধারণ প্যাটার্নগুলি মোকাবেলা করার আগে এই কৌশলটি করেছি । সাধারণত অধিগ্রহণ লক হয় , তবে আরও কিছু রয়েছে । সমস্যা হ'ল এটি সর্বদা হ্যাকের মতো বোধ করে যেহেতু বস্তুটি এতটা "ডিসপোজেবল -এন্ড-অফ-এ-স্কোপ-সক্ষম " এর মতো এতটা ডিসপোজযোগ্য নয় ।

ডগ,

যখন আমরা ব্যবহারের বিবৃতিটি [sic] স্থির করেছিলাম, তখন আমরা বিষয়টিকে নিষ্পত্তি করার ক্ষেত্রে আরও সুনির্দিষ্ট কিছু না করে "নামকরণ" করার সিদ্ধান্ত নিয়েছিলাম যাতে এটি ঠিক এই দৃশ্যের জন্য ব্যবহার করা যায় could


4
ঠিক আছে যে উক্তিটি যখন "" ঠিক এই দৃশ্য "বলেছেন তখন তিনি কী উল্লেখ করছেন, কারণ আমি সন্দেহ করি যে তিনি ভবিষ্যতের এই প্রশ্নটি উল্লেখ করছেন।
ফ্র্যাঙ্ক শ্যুইটারম্যান

3
@ ফ্র্যাঙ্ক শ্যুইটারম্যান: আমি উদ্ধৃতিটি শেষ করেছি। স্পষ্টতই, সি # টিমের লোকেরা মনে করেছিল যে usingবৈশিষ্ট্যটি কেবলমাত্র সম্পদ নিষ্পত্তির মধ্যে সীমাবদ্ধ থাকবে না
প্যারাসেবল

11

এটি পিচ্ছিল opeাল। আইডিসপোজেবলের একটি চুক্তি রয়েছে, এটি একটি ফাইনালাইজারের দ্বারা ব্যাক আপ। একটি ফাইনালাইজার আপনার ক্ষেত্রে অকেজো। আপনি ক্লায়েন্টকে ব্যবহারের বিবৃতিটি ব্যবহার করতে বাধ্য করতে পারবেন না, কেবল তাকে এটি করতে উত্সাহ দিন। আপনি এ জাতীয় পদ্ধতিতে এটি জোর করতে পারেন:

void UseMeUnlocked(Action callback) {
  Unlock();
  try {
    callback();
  }
  finally {
    Lock();
  }
}

তবে তা লামদাস ছাড়াই কিছুটা বিশ্রী পেতে। এটি বলেছিল, আমি আপনার মতো আইডিস্পোজেবল ব্যবহার করেছি।

আপনার পোস্টে তবে একটি বিশদ রয়েছে যা এটিকে বিপজ্জনকভাবে একটি অ্যান্টি-প্যাটার্নের নিকটে পরিণত করে। আপনি উল্লেখ করেছেন যে এই পদ্ধতিগুলি একটি ব্যতিক্রম ছুঁড়ে ফেলতে পারে। এটি কলার উপেক্ষা করতে পারে এমন কিছু নয়। তিনি সে সম্পর্কে তিনটি কাজ করতে পারেন:

  • কিছুই করবেন না, ব্যতিক্রমটি পুনরুদ্ধারযোগ্য নয়। স্বাভাবিক ক্ষেত্রে। আনলক কল করা কোনও বিষয় নয়।
  • ব্যতিক্রম ধরুন এবং পরিচালনা করুন
  • তার কোডে রাষ্ট্র পুনরুদ্ধার করুন এবং ব্যতিক্রমটি কল চেইনটি পাস করুন let

দ্বিতীয়টির জন্য কলার স্পষ্টভাবে একটি চেষ্টা ব্লক লেখার প্রয়োজন। এখন ব্যবহারের বিবৃতিটি পায়। এটি কোনও ক্লায়েন্টকে কোমায় পরিণত করতে পারে যা তাকে বিশ্বাস করে যে আপনার শ্রেণি রাষ্ট্রের যত্ন নিচ্ছে এবং কোনও অতিরিক্ত কাজ করার দরকার নেই। এটি প্রায় কখনই নির্ভুল হয় না।


জোর করে মামলাটি উপরের "হার্জমিস্টার ডার ওয়েল্টেন" দিয়েছিল, আমি মনে করি - এমনকি যদি ওপি উদাহরণটি পছন্দ করে না মনে করে।
বেনিয়ামিন পোডসুন

হ্যাঁ, আমি তাকে SafeExecuteজেনেরিক এক্সটেনশন পদ্ধতি হিসাবে ব্যাখ্যা করেছি । আমি এখন দেখছি যে এটি সম্ভবত এমন একটি Fribbleপদ্ধতি হিসাবে বোঝানো হয়েছিল যা কল করে Unlock()এবং Lock()মোড়ানো চেষ্টা / অবশেষে। আমার খারাপ।
জোহান জেরেল

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

7

আসল বিশ্বের উদাহরণ হ'ল এএসপিএনটি এমভিসি-র বিগেনফর্ম। মূলত আপনি লিখতে পারেন:

Html.BeginForm(...);
Html.TextBox(...);
Html.EndForm();

অথবা

using(Html.BeginForm(...)){
    Html.TextBox(...);
}

এইচটিএমএল.এন্ডফোর্ম ডিসপোজ কল করে এবং ডিসপোজকে কেবল </form>ট্যাগটি আউটপুট করে । এ সম্পর্কে ভাল বিষয়টি হ'ল}} বন্ধনীগুলি একটি দৃশ্যমান "স্কোপ" তৈরি করে যা ফর্মের মধ্যে কী আছে এবং কী নয় তা সহজেই সহজ করে তোলে।

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

নিম্নলিখিত দুটি নিয়ম যদি সত্য হয় তবে ব্যক্তিগতভাবে আমি এটি ব্যবহার করব তবে আমার দ্বারা এটি নির্বিচারে সেট করা হয়েছে:

  • নিষ্পত্তি হ'ল এমন একটি ফাংশন হওয়া উচিত যা সর্বদা চালাতে হয়, তাই নুল-চেকগুলি ছাড়া কোনও শর্ত থাকা উচিত নয়
  • নিষ্পত্তি () এর পরে, অবজেক্টটি পুনরায় ব্যবহারযোগ্য হবে না। আমি যদি পুনঃব্যবহারযোগ্য অবজেক্টটি চাইতাম তবে আমি এটিকে নিষ্পত্তি না করে খোলা / বন্ধ পদ্ধতিগুলি দেই। তাই কোনও নিষ্পত্তিযোগ্য অবজেক্টটি ব্যবহার করার চেষ্টা করার সময় আমি একটি অবৈধপ্রকাশের ধারণাটি নিক্ষেপ করি।

শেষে, এটি সব প্রত্যাশা সম্পর্কে। যদি কোনও বস্তু আইডিস্পোজেবল কার্যকর করে, আমি ধরে নিই এটির জন্য কিছু পরিষ্কার করার দরকার আছে, তাই আমি এটিকে কল করি। আমি মনে করি এটি সাধারণত "শাটডাউন" ফাংশনটি বীট করে।

বলা হচ্ছে, আমি এই লাইনটি পছন্দ করি না:

this.Frobble.Fiddle();

ফ্রববল্যাঞ্জিটার যেমন এখন ফ্রববলের "মালিকানা" পেয়েছে, আমি অবাক হয়েছি যে, যদি জিনেটরে ফ্রিবলকে তার পরিবর্তে ফ্রিডাল বলা ভাল না হয়?


আপনার "আমি এই লাইনটি পছন্দ করি না" সম্পর্কে - প্রশ্নটি গঠনের সময় আমি আসলে সংক্ষেপে এটি করার কথা ভেবেছিলাম, তবে আমি আমার প্রশ্নের শব্দার্থবিজ্ঞানকে বিশৃঙ্খলা করতে চাইনি। তবে আমি আপনার সাথে একমত। ধরনের। :)
জোহান জেরেল

1
মাইক্রোসফ্ট থেকে নিজেই একটি উদাহরণ দেওয়ার জন্য উত্সাহিত। নোট করুন যে ক্ষেত্রে আপনি উল্লেখ করেছেন সেখানে ছুঁড়ে ফেলার জন্য একটি নির্দিষ্ট ব্যতিক্রম রয়েছে: অবজেক্টডিসপোজড এক্সসেপশন।
অ্যান্টিটুন

4

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


4

এটির উপর নজর রেখে: আমি এখানে বেশিরভাগের সাথে একমত যে এটি ভঙ্গুর, তবে দরকারী useful আমি আপনাকে সিস্টেম.ট্রানজেকশন.ট্র্যাশনসকোপ ক্লাসে নির্দেশ করতে চাই, এটি আপনার মতো করার মতো কিছু করে।

সাধারণত আমি সিনট্যাক্স পছন্দ করি, এটি আসল মাংস থেকে প্রচুর গোলমাল সরিয়ে দেয়। দয়া করে সহায়ক শ্রেণিকে একটি ভাল নাম দেওয়ার কথা বিবেচনা করুন - সম্ভবত ... উপরোক্ত উদাহরণের মতো ব্যাপ্তি। নামটি দেওয়া উচিত যা এটি কোডের একটি অংশকে আবদ্ধ করে। * স্কোপ, * ব্লক বা অনুরূপ কিছু এটি করা উচিত।


1
স্কোপগার্ড লোকিকে যাত্রা করার আগেই স্ক্যান্ডগার্ড সম্পর্কে আন্ড্রে আলেকজান্দ্রেস্কুর একটি পুরানো সি ++ নিবন্ধ থেকে "জানিটর" এসেছে।
জোহান জেরেল 20'10

@ বেঞ্জামিন: আমি লেনদেনস্কোপ ক্লাস পছন্দ করি, এর আগে এর আগে শুনিনি। সম্ভবত কারণ আমি। নেট সিএফ ল্যান্ডে আছি, যেখানে এটি অন্তর্ভুক্ত নেই ... :-(
জোহান জেরেল

4

দ্রষ্টব্য: আমার দৃষ্টিভঙ্গি সম্ভবত আমার সি ++ ব্যাকগ্রাউন্ড থেকে পক্ষপাতদুষ্ট, সুতরাং আমার উত্তরের মানটি সম্ভাব্য পক্ষপাতের বিরুদ্ধে মূল্যায়ন করা উচিত ...

সি # ভাষার স্পেসিফিকেশন কী বলে?

সি # ভাষার নির্দিষ্টকরণের উদ্ধৃতি :

8.13 ব্যবহারের বিবৃতি

[...]

একটি রিসোর্স একটি বর্গ বা struct হয় যে কার্যকরী System.IDisposable, যা নিষ্পত্তি নামে একজন একক parameterless পদ্ধতি অন্তর্ভুক্ত করা হয়েছে। সংস্থানটি ব্যবহার করছে এমন কোডগুলি ডিসপোজে কল করতে পারে যে সূত্রটির আর প্রয়োজন নেই indicate যদি নিষ্পত্তি না বলা হয়, তবে অবশেষে আবর্জনা সংগ্রহের ফলাফল হিসাবে স্বয়ংক্রিয় নিষ্পত্তি ঘটে।

কোড পারেন যে কোন রিসোর্সকে ব্যবহার করছে , অবশ্যই, কোড দ্বারা শুরু হয় usingশব্দ এবং সুযোগ সংযুক্ত না হওয়া পর্যন্ত যাচ্ছে using

সুতরাং আমি অনুমান করি এটি ঠিক আছে কারণ লকটি একটি সংস্থান।

সম্ভবত মূলশব্দটি usingখারাপভাবে বেছে নেওয়া হয়েছিল। সম্ভবত এটি বলা উচিত ছিল scoped

তারপরে, আমরা প্রায় কোনও কিছুকে একটি উত্স হিসাবে বিবেচনা করতে পারি। একটি ফাইল হ্যান্ডেল। একটি নেটওয়ার্ক সংযোগ ... একটি থ্রেড?

একটি সুতো ???

(বা আপত্তিজনক) usingকীওয়ার্ডটি ব্যবহার করছেন?

সুযোগটি প্রস্থান করার আগে থ্রেডের কাজ শেষ হয়েছে কিনা তা নিশ্চিত করতে (আব) কীওয়ার্ডটি ব্যবহার করা চকচকে হবে using?

ভেষজ সুটার মনে হয় এটি চকচকে , কারণ তিনি কোনও থ্রেডের কাজ শেষ হওয়ার জন্য অপেক্ষা করার জন্য আইডিসপোজ প্যাটার্নটির একটি আকর্ষণীয় ব্যবহার উপস্থাপন করেন:

http://www.drdobbs.com/go-parallel/article/showArticle.jhtml?articleID=225700095

নিবন্ধটি থেকে কপি-পেস্ট করা কোডটি এখানে:

// C# example
using( Active a = new Active() ) {    // creates private thread
       
       a.SomeWork();                  // enqueues work
       
       a.MoreWork();                   // enqueues work
       
} // waits for work to complete and joins with private thread

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

~Active() {
    // etc.
    thd->join();
 }

সুতরাং, যতক্ষণ হার্ব সম্পর্কিত, এটি চকচকে


3

আমি বিশ্বাস করি আপনার প্রশ্নের উত্তর হ'ল না, এটি কোনও অপব্যবহার হবে না IDisposable

আমি যেভাবে IDisposableইন্টারফেসটি বুঝতে পারি তা হ'ল একবার নিষ্পত্তি হয়ে গেলে আপনি কোনও বস্তুর সাথে কাজ করার কথা নয় (আপনি আপনাকে তার Disposeপদ্ধতিটি যতবার ইচ্ছা কল করার অনুমতি দেওয়া হয়েছে তা বাদে )।

যেহেতু আপনি প্রতিবার স্টেটমেন্টটি পাওয়ার সময় স্পষ্টভাবে একটি নতুন তৈরি FrobbleJanitorকরেন using, আপনি কখনও একই FrobbeJanitorজিনিসটি দু'বার ব্যবহার করবেন না । এবং যেহেতু এটির উদ্দেশ্য অন্য কোনও বিষয় পরিচালনা করা, Disposeএই ("পরিচালিত") সংস্থানটি মুক্ত করার পক্ষে এটি উপযুক্ত মনে হয়।

(বিটিডব্লু।, Disposeপ্রায়শই সর্বদা যথাযথ প্রয়োগের প্রমাণিত স্ট্যান্ডার্ড স্যাম্পল কোডটি নির্দেশ করে যে পরিচালিত সংস্থানগুলিও বিনামূল্যে মুক্তি দেওয়া উচিত, কেবল ফাইল-সিস্টেম হ্যান্ডলগুলির মতো পরিচালনা-ব্যবস্থাবিহীন সংস্থানগুলিতে নয়))

কেবলমাত্র আমি যেখানে ব্যক্তিগতভাবে চিন্তিত তা হ'ল যেখানে & অপারেশনগুলি সরাসরি দৃশ্যমান সেখানে using (var janitor = new FrobbleJanitor())আরও স্পষ্টত try..finallyব্লকের চেয়ে যা ঘটছে তা কম স্পষ্ট । তবে কোন পদ্ধতির গ্রহণ করা সম্ভবত ব্যক্তিগত পছন্দগুলির বিষয় হিসাবে নেমে আসে।LockUnlock


1

এটি আপত্তিজনক নয়। তারা তাদের জন্য তৈরি করা হচ্ছে তা আপনি তাদের ব্যবহার করছেন। তবে আপনাকে নিজের প্রয়োজন অনুসারে একে অপরকে বিবেচনা করতে হতে পারে। উদাহরণস্বরূপ যদি আপনি 'শৈল্পিকতা' বেছে নিচ্ছেন তবে আপনি 'ব্যবহার করে' ব্যবহার করতে পারেন তবে যদি আপনার কোডের টুকরোগুলি অনেক সময় কার্যকর হয় তবে কার্য সম্পাদনের কারণে আপনি 'চেষ্টা' .. 'অবশেষে' রচনাগুলি ব্যবহার করতে পারেন। কারণ 'ব্যবহার' এর মধ্যে সাধারণত কোনও বস্তুর ক্রিয়া জড়িত।


1

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

আমি ফ্রেব্বলজ্যানিটারের নাম রাখব যদিও সম্ভবত ফ্রবললকসেশন এর মতো কিছুতে।


নতুন নামকরণ সম্পর্কে - আমি লক / আনলক নিয়ে যে প্রাথমিক কারণে আচরণ করেছি তার "জানিটর" ব্যবহার করেছি। আমি ভেবেছিলাম এটি অন্য নামের পছন্দ সহ ছড়াচ্ছে। ;-) যদি আমি এই কোডটি আমার কোড বেস জুড়ে একটি নিদর্শন হিসাবে ব্যবহার করি তবে আমি অবশ্যই আরও সাধারণভাবে বর্ণনামূলক কিছু অন্তর্ভুক্ত করব, যেমন আপনি "সেশন" দিয়ে গেছেন। যদি এটি পুরানো সি ++ দিন হত তবে আমি সম্ভবত ফ্রববলউনলকস্কোপ ব্যবহার করতাম।
জোহান জেরেল 20'10
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.