জাভা / সি # আরআইআই প্রয়োগ করতে পারে না কেন?


29

প্রশ্ন: জাভা / সি # আরআইআই বাস্তবায়ন করতে পারে না কেন?

স্পষ্টকরণ: আমি সচেতন যে আবর্জনা সংগ্রহকারী নিরোধক নয়। সুতরাং বর্তমান ভাষার বৈশিষ্ট্যগুলির সাথে স্কোপের প্রস্থানটিতে কোনও সামগ্রীর ডিসপোজ () পদ্ধতিটি স্বয়ংক্রিয়ভাবে কল করা সম্ভব নয়। কিন্তু এই জাতীয় সংযোজনীয় বৈশিষ্ট্য যুক্ত করা যেতে পারে?

আমার বোঝার:

আমি অনুভব করি যে RAII এর বাস্তবায়ন অবশ্যই দুটি প্রয়োজনীয়তা পূরণ করবে:
১. কোনও উত্সের আজীবন অবশ্যই একটি সুযোগের সাথে আবদ্ধ থাকতে হবে।
2. অন্তর্নিহিত। সংস্থানটি মুক্ত হওয়া অবশ্যই প্রোগ্রামারের স্পষ্ট বিবৃতি ছাড়াই ঘটবে। স্পষ্ট বক্তব্য ছাড়াই মেমরি মুক্ত করা কোনও আবর্জনা সংগ্রাহকের সাথে সমতুল্য। "ফলস্বরূপ" কেবল শ্রেণীর ব্যবহারের সময়ে ঘটতে হবে। শ্রেণিকালীন গ্রন্থাগার স্রষ্টাকে অবশ্যই অবশ্যই ডেস্ট্রাক্টর বা নিষ্পত্তি () পদ্ধতি প্রয়োগ করতে হবে।

জাভা / সি # সন্তুষ্ট পয়েন্ট ১। সি # তে একটি সংস্থান প্রয়োগকারী আইডিস্পোজেবল একটি "ব্যবহার করে" সুযোগের সাথে আবদ্ধ হতে পারে:

void test()
{
    using(Resource r = new Resource())
    {
        r.foo();
    }//resource released on scope exit
}

এটি পয়েন্ট ২ টি পূরণ করে না The প্রোগ্রামারকে অবশ্যই স্পষ্টভাবে বস্তুকে একটি বিশেষ "ব্যবহার করে" সুযোগের সাথে আবদ্ধ করতে হবে। প্রোগ্রামাররা স্পষ্টভাবে একটি ফাঁকে ফাঁকে তৈরি করে, উত্সটিকে কোনও স্কোপের সাথে বেঁধে রাখতে (এবং করতে) ভুলে যেতে পারে।

প্রকৃতপক্ষে "ব্যবহার করে" ব্লকগুলি সংকলক কর্তৃক চেষ্টা-অবশেষে নিষ্পত্তি () কোডে রূপান্তরিত হয়। এটি চেষ্টা-অবশেষে নিষ্পত্তি () প্যাটার্নের একই স্পষ্ট প্রকৃতি রয়েছে। একটি নিখুঁত মুক্তি ছাড়া, একটি সুযোগ হুক সিনট্যাকটিক চিনি হয়।

void test()
{
    //Programmer forgot (or was not aware of the need) to explicitly
    //bind Resource to a scope.
    Resource r = new Resource(); 
    r.foo();
}//resource leaked!!!

আমি মনে করি জাভা / সি # তে একটি ভাষা বৈশিষ্ট্য তৈরি করা উপযুক্ত special বিশেষ স্মৃতিগুলিকে স্মার্ট পয়েন্টারটির মাধ্যমে স্ট্যাকের কাছে ঝুঁকতে দেওয়া মঞ্জুরি দেয়। বৈশিষ্ট্যটি আপনাকে স্কোপ-বাউন্ড হিসাবে কোনও শ্রেণি পতাকাঙ্কিত করতে দেয়, যাতে এটি সর্বদা স্ট্যাকের একটি হুক দিয়ে তৈরি হয়। বিভিন্ন ধরণের স্মার্ট পয়েন্টারগুলির জন্য বিকল্প থাকতে পারে।

class Resource - ScopeBound
{
    /* class details */

    void Dispose()
    {
        //free resource
    }
}

void test()
{
    //class Resource was flagged as ScopeBound so the tie to the stack is implicit.
    Resource r = new Resource(); //r is a smart-pointer
    r.foo();
}//resource released on scope exit.

আমি মনে করি অনর্থক "এটি মূল্যবান"। ঠিক যেমন জঞ্জাল সংগ্রহের ফলস্বরূপ "এটি মূল্যবান"। সুস্পষ্ট ব্যবহারের মাধ্যমে ব্লকগুলি চোখকে সতেজ করে তুলছে, তবে শেষ পর্যন্ত-নিষ্পত্তি করে চেষ্টা করুন () এর চেয়ে কোনও লাভজনক প্রস্তাব রাখবেন না।

জাভা / সি # ভাষায় এই জাতীয় বৈশিষ্ট্যটি প্রয়োগ করা কি অবাস্তব? এটি পুরানো কোডটি না ভেঙে চালু করা যেতে পারে?


3
এটি অবৈধ নয়, এটি অসম্ভব । সি # স্ট্যান্ডার্ডটি ডেস্ট্রাক্টর / Disposeগুলি সর্বদা চালিত হওয়ার গ্যারান্টি দেয় না , তারা কীভাবে ট্রিগার হয় তা নির্বিশেষে। সুযোগের শেষে অন্তর্নিহিত ধ্বংস যোগ করা এতে সহায়তা করবে না।
টেলাস্টিন

20
@ টেলাস্টিন হাহ? সি # স্ট্যান্ডার্ড এখন যা বলেছে তা কোনও প্রাসঙ্গিক নয়, যেহেতু আমরা সেই নথিটি পরিবর্তন করার বিষয়ে আলোচনা করছি। একমাত্র বিষয়টি হ'ল এটি করা ব্যবহারিক কিনা এবং তার জন্য গ্যারান্টির বর্তমান অভাব সম্পর্কে একমাত্র আকর্ষণীয় বিট হ'ল এই গ্যারান্টিটির অভাবের কারণ reasons নোট usingকরুন কার্যকর করার Dispose জন্য গ্যারান্টিযুক্ত (ভাল, একটি ব্যতিক্রম ছোঁড়া ছাড়াই আকস্মিকভাবে মারা যাওয়ার প্রক্রিয়াটি ছাড় দেওয়া, যার পরে সমস্ত ক্লিনআপ সম্ভবত মোটা হয়ে যায়)।

4
এর প্রতিলিপি জাভার ডেভেলপারদের সচেতনভাবে RAII পরিত্যাগ করেছেন? যদিও গৃহীত উত্তর সম্পূর্ণ ভুল। সংক্ষিপ্ত উত্তরটি হ'ল জাভা মান (স্ট্যাক) শব্দার্থবিজ্ঞানের পরিবর্তে রেফারেন্স (হিপ) শব্দার্থবিজ্ঞান ব্যবহার করে , সুতরাং নির্মূল চূড়ান্তকরণ খুব দরকারী / সম্ভব নয়। সি শার্প করে মূল্য শব্দার্থবিদ্যা (আছে ), কিন্তু তারা সাধারণত খুব বিশেষ ক্ষেত্রে ছাড়া এড়িয়ে যাওয়া হয়। এছাড়াও দেখুনstruct
ব্লুরাজা - ড্যানি পিফ্লুঘুফুট

2
এটি অনুরূপ, সঠিক সদৃশ নয়।
ম্যানেরো

উত্তর:


17

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

যদি স্ট্যাক-বাউন্ড টাইপের পরিবর্তকের জীবনকাল শেষ হয়, তবে Disposeযে বস্তুকে এটি উল্লেখ করা হয়েছে তার জন্য কল করুন

ভাষা সম্পর্কিত প্রাসঙ্গিক বিভাগে এবং সম্পন্ন করা। আমি সাময়িক মানগুলির সমস্যাটিকে উপেক্ষা করব ( new Resource().doSomething()) যা আরও সাধারণ শব্দ দ্বারা সমাধান করা যায়, এটি সবচেয়ে গুরুতর সমস্যা নয়। উদাহরণস্বরূপ, এই কোডটি নষ্ট হয়ে যাবে (এবং এই ধরণের জিনিসটি সাধারণভাবে করা অসম্ভব হয়ে পড়ে):

File openSavegame(string id) {
    string path = ... id ...;
    File f = new File(path);
    // do something, perhaps logging
    return f;
} // f goes out of scope, caller receives a closed file

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

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


আপনার কপি / মুভ কনস্ট্রাক্টরের দরকার কেন? ফাইল একটি রেফারেন্স টাইপ স্থির। সেই পরিস্থিতিতে চটি যা পয়েন্টার সেটিকে কলারের কাছে অনুলিপি করা হয় এবং এটি সংস্থানটি নিষ্পত্তি করা দায়বদ্ধ (সংকলক
স্পষ্টতই

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

আপনি এখন যা বলেছিলেন তা দেখতে আমি ব্যর্থ (আমি আপনাকে ভুল বলছি না)। অবজেক্টটির একটি সংস্থান রয়েছে, রেফারেন্স নয়।
ম্যানেরো

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

1
@ বিগাউন অন্য কথায়, Disposeকোনও রেফারেন্স পালিয়ে গেলে কল করবেন না ? এস্কেপ বিশ্লেষণ একটি পুরানো এবং কঠিন সমস্যা, এটি ভাষাতে আরও পরিবর্তন না করে সবসময় কাজ করবে না। যখন কোনও রেফারেন্স অন্য (ভার্চুয়াল) পদ্ধতিতে ( something.EatFile(f);) পাস করা হয় f.Dispose, তখন সুযোগের শেষে ডাকা উচিত ? যদি হ্যাঁ, আপনি fপরে ব্যবহারের জন্য সেই কলকারীদের ভাঙা । যদি তা না হয়, যদি কলার সঞ্চয় না করে তবে আপনি সংস্থানটি ফাঁস করুন f। এটি অপসারণের একমাত্র কিছু সহজ উপায় হ'ল একটি লিনিয়ার টাইপ সিস্টেম, যা (আমি ইতিমধ্যে পরে আমার উত্তরে আলোচনা করেছি) পরিবর্তে অন্যান্য অনেক জটিলতার পরিচয় দেয়।

26

জাভা বা সি # এর জন্য এই জাতীয় কিছু বাস্তবায়নে সবচেয়ে বড় সমস্যাটি সংস্থান স্থানান্তর কীভাবে কাজ করবে তা নির্ধারণ করা হবে। সুযোগের অতিক্রম করে আপনার উত্সটির আয়ু বাড়ানোর কোনও উপায় প্রয়োজন। বিবেচনা:

class IWrapAResource
{
    private readonly Resource resource;
    public IWrapAResource()
    {
        // Where Resource is scope bound
        Resource builder = new Resource(args, args, args);

        this.resource = builder;
    } // Uh oh, resource is destroyed
} // Crap, there's no scope for IWrapAResource we can bind to!

সবচেয়ে খারাপ এটি হ'ল এটি প্রয়োগকারীদের কাছে এটি স্পষ্ট নাও হতে পারে IWrapAResource:

class IWrapSomething<T>
{
    private readonly T resource; // What happens if T is Resource?
    public IWrapSomething(T input)
    {
        this.resource = input;
    }
}

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


ধরে নেওয়া যায় যে সুযোগের বাইরে চলে যাওয়ার পরে আপনার কোনও ভেরিয়েবলটি উল্লেখ করার দরকার নেই (এবং সত্যই এরকম কোনও প্রয়োজন হওয়া উচিত নয়), আমি দাবি করি যে আপনি এখনও কোনও চূড়ান্তকরণের জন্য এটি চূড়ান্তরূপে লিখে স্ব-নিষ্পত্তি করতে পারবেন । অবজেক্টটি আবর্জনা সংগ্রহের ঠিক আগে ফাইনালাইজারকে ডাকা হয়। এমএসডিএন.মাইক্রোসফটকম /en-us/library/0s71x931.aspx
রবার্ট হার্ভে

8
@ রবার্ট: একটি সঠিকভাবে লিখিত প্রোগ্রাম চূড়ান্তরূপী চালানো কখনও ধরে নিতে পারে না। ব্লগস.এমএসডিএন
বিলি ওনিল

1
হুঁ। ঠিক আছে, এ কারণেই সম্ভবত তারা usingবিবৃতিটি নিয়ে এসেছিল ।
রবার্ট হার্ভে

2
যথাযথভাবে। এটি সি ++ তে নবাগত বাগগুলির একটি বিশাল উত্স এবং এটি জাভা / সি # তেও থাকবে। জাভা / সি # যে সংস্থার ধ্বংস হওয়ার কথা রয়েছে তার রেফারেন্স ফাঁস করার ক্ষমতাটি হারাবেন না, তবে এটিকে স্পষ্ট এবং alচ্ছিক উভয় করে তারা প্রোগ্রামারকে স্মরণ করিয়ে দেয় এবং কী করতে হবে তার একটি সচেতন পছন্দ দেয়।
আলেকজান্ডার ডাবিনস্কি

1
@ এসভিক এটি IWrapSomethingনিষ্পত্তি করা শেষ নয় T। যে কেউ তৈরি করেছেন সে Tসম্পর্কে এটি উদ্বিগ্ন usingহওয়া দরকার, IDisposableনিজে ব্যবহার করা হোক না কেন , কিছু অ্যাড-হক রিসোর্স লাইফাইসাইকেল স্কিম থাকুক ।
আলেকসান্দ্র ডাবিনস্কি

13

আরআইআই সি # এর মতো কোনও ভাষাতে কাজ করতে না পারার কারণ এটি সি ++ তে কাজ করে, কারণ সি ++ এ আপনি সিদ্ধান্ত নিতে পারেন যে কোনও বস্তু সত্যই অস্থায়ী কিনা (এটি স্ট্যাকের উপর বরাদ্দ দিয়ে) বা দীর্ঘস্থায়ী কিনা (দ্বারা newপয়েন্টার ব্যবহার করে এবং ব্যবহার করে এটি গাদাতে বরাদ্দ করা হয় )।

সুতরাং, সি ++ এ আপনি এরকম কিছু করতে পারেন:

void f()
{
    Foo f1;
    Foo* f2 = new Foo();
    Foo::someStaticField = f2;

    // f1 is destroyed here, the object pointed to by f2 isn't
}

সি # তে, আপনি দুটি কেসের মধ্যে পার্থক্য করতে পারবেন না, সুতরাং কম্পাইলারটি অবজেক্টটি চূড়ান্ত করবেন কিনা তা সম্পর্কে কোনও ধারণা নেই।

আপনি যা করতে পারেন তা হ'ল একধরনের বিশেষ স্থানীয় পরিবর্তনশীল ধরণের পরিচয় করিয়ে দেওয়া, যা আপনি ক্ষেত্রগুলিতে স্থাপন করতে পারবেন না ইত্যাদি * এবং সুযোগের বাইরে চলে গেলে এটি স্বয়ংক্রিয়ভাবে নিষ্পত্তি হবে। সি ++ / সিএলআই ঠিক কী করে। সি ++ / সিএলআই-তে আপনি এই জাতীয় কোড লিখেছেন:

void f()
{
    Foo f1;
    Foo^ f2 = gcnew Foo();
    Foo::someStaticField = f2;

    // f1 is disposed here, the object pointed to by f2 isn't
}

এটি মূলত নিম্নলিখিত সি # এর মতো একই আইএলকে সংকলন করে:

void f()
{
    using (Foo f1 = new Foo())
    {
        Foo f2 = new Foo();
        Foo.someStaticField = f2;
    }
    // f1 is disposed here, the object pointed to by f2 isn't
}

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

* অপারেটরের সমতুল্য ছাড়া নয় &, যা সি ++ / সিএলআইতে রয়েছে %। যদিও এটি করা "অনিরাপদ" এই অর্থে যে পদ্ধতিটি শেষ হওয়ার পরে, ক্ষেত্রটি কোনও নিষ্পত্তিযোগ্য বস্তুর রেফারেন্স দেবে।


1
সি # যদি তুচ্ছভাবে আরআইআইআই করতে পারে যদি এটি structডি এর মতো ধরণের ডেস্ট্রাক্টরদের অনুমতি দেয়।
জান হুডেক

6

যদি আপনাকে usingব্লকগুলি বিরক্ত করে তবে তা তাদের স্পষ্টতই সাক্ষ্যদাতা হয়, সম্ভবত আমরা সি # স্পেসটি পরিবর্তনের পরিবর্তে কম স্পষ্টকর্তার দিকে একটি ছোট শিশুর পদক্ষেপ নিতে পারি। এই কোডটি বিবেচনা করুন:

public void ReadFile ()
{
  string filename = "myFile.dat";
  local Stream file = File.Open(filename);
  file.Read(blah blah blah);
}

localআমি যুক্ত করা কিওয়ার্ডটি দেখুন ? এটি কেবল কিছুটা আরও সিনট্যাকটিক চিনি যুক্ত করা ঠিক যেমন using, কম্পাইলারকে ভেরিয়েবলের স্কোপের শেষে Disposeএকটি finallyব্লকে ডাকতে বলা । এটাই সব। এটি সম্পূর্ণ সমতুল্য:

public void ReadFile ()
{
  string filename = "myFile.dat";
  using (Stream file = File.Open(filename))
  {
      file.Read(blah blah blah);
  }
}

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

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


1
@ মাইকে 30 কিন্তু এটিকে সংজ্ঞা সংকেতে নিয়ে যাওয়া আপনাকে অন্যদের তালিকাভুক্ত সমস্যার দিকে নিয়ে যায় - আপনি যদি পয়েন্টারটিকে অন্য কোনও পদ্ধতিতে পাস করেন বা ফাংশন থেকে ফিরিয়ে দেন তবে কী হবে? এইভাবে স্কোপিংটি স্কোপে ঘোষণা করা হয়, অন্য কোথাও নয়। কোনও প্রকারটি ডিসপোজেবল হতে পারে তবে ডিসপোজকে কল করা এটি নির্ভর করে না।
অব্নার শাহর-কাশতান

3
@ মাইক 30: মেহ। এই সমস্ত সিনট্যাক্সটি হ'ল ধনুর্বন্ধনীগুলি সরিয়ে এবং এক্সটেনশনের মাধ্যমে তারা সরবরাহ করে স্কোপিং নিয়ন্ত্রণ।
রবার্ট হার্ভে

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

1
ভাষা নকশায় আধা-ব্যবহারিক অনুশীলন নিয়ে আমার কোনও সমস্যা হয়নি।
অব্নার শাহর-কাশতান

1
@RobertHarvey। সি # তে বর্তমানে প্রয়োগ করা হয়নি এমন কোনও কিছুর বিরুদ্ধে আপনার পক্ষপাতিত্ব বলে মনে হচ্ছে। আমরা সি # 1.0 এর সাথে সন্তুষ্ট থাকলে আমাদের জেনেরিকস, লিনক, ইউজিং-ব্লকস, আইপ্লেমিক্যাল প্রকারগুলি ইত্যাদি থাকত না। এই বাক্য গঠনটি অনর্থক সমস্যার সমাধান করে না, তবে বর্তমানের সাথে আবদ্ধ হওয়া ভাল চিনি।
মাইকে

1

আবর্জনা-সংগৃহীত ভাষায় RAII কীভাবে কাজ করে তার উদাহরণের জন্য withপাইথনে কীওয়ার্ডটি পরীক্ষা করে দেখুন । নির্বিচারে-ধ্বংস হওয়া বস্তুর উপর নির্ভর করার পরিবর্তে এটি আপনাকে একটি নির্দিষ্ট বর্ণনামূলক স্কোপে সংযুক্ত __enter__()এবং __exit__()পদ্ধতিগুলি দেয়। একটি সাধারণ উদাহরণ:

with open('output.txt', 'w') as f:
    f.write('Hi there!')

সি ++ এর আরআইআই স্টাইলের মতোই, ফাইলটি বন্ধ হয়ে যাবে সেই ব্লকটি থেকে বেরোনোর ​​পরে, এটি 'সাধারণ' প্রস্থান, এ break, তাত্ক্ষণিক returnবা কোনও ব্যতিক্রম নয়।

মনে রাখবেন যে open()কলটি স্বাভাবিক ফাইল খোলার ফাংশন। এই কাজটি করতে, প্রত্যাবর্তিত ফাইল অবজেক্টে দুটি পদ্ধতি রয়েছে:

def __enter__(self):
  return self
def __exit__(self):
  self.close()

এটি পাইথনের সাধারণ আইডিয়োম: উত্সগুলির সাথে সম্পর্কিত যে জিনিসগুলি সাধারণত এই দুটি পদ্ধতি অন্তর্ভুক্ত করে।

নোট করুন যে ফাইল অবজেক্টটি __exit__()কল করার পরেও বরাদ্দ থাকতে পারে , গুরুত্বপূর্ণ বিষয়টি এটি বন্ধ রয়েছে।


7
withপাইথনে প্রায় ঠিক using# সি এর মতো , এবং এই প্রশ্নটি যতটা RAII নয় ততটা নয়।

1
পাইথনের "উইথ" স্কোপ-বাউন্ড রিসোর্স ম্যানেজমেন্ট তবে এটি স্মার্ট-পয়েন্টারের ফলস্বরূপ অনুপস্থিত। পয়েন্টারটিকে স্মার্ট হিসাবে ঘোষণা করার কাজটিকে "স্পষ্ট" হিসাবে বিবেচনা করা যেতে পারে, তবে সংকলক যদি বস্তুর ধরণের অংশ হিসাবে স্মার্টনেস প্রয়োগ করে তবে এটি "অন্তর্নিহিত" দিকে ঝুঁকবে।
মাইকে

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

1
প্রকৃতপক্ষে, আমি জাভা এবং সি # সুস্পষ্টভাবে নির্মাণের পক্ষে দৃ say়ভাবে বলেছি এটি ন্যায্য বলে মনে করি। অন্যথায়, ইন্টারফেস এবং উত্তরাধিকার ব্যবহারের অন্তর্নিহিত সমস্ত অনুষ্ঠানকে কেন বিরক্ত করবেন?
রবার্ট হার্ভে

1
@ ডেলান, গো'র অন্তর্নিহিত ইন্টারফেস রয়েছে।
জাভিয়ের
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.