কোনও রিটার্ন স্টেটমেন্টটি কোনও লকের ভিতরে বা বাইরে থাকা উচিত?


142

আমি কেবল বুঝতে পেরেছিলাম যে আমার কোডের কোনও জায়গায় আমার কাছে লকের ভিতরে এবং বাইরে বাইরে কোনও সময় বিবরণী রয়েছে। কোনটি সবচাইতে ভাল?

1)

void example()
{
    lock (mutex)
    {
    //...
    }
    return myData;
}

2)

void example()
{
    lock (mutex)
    {
    //...
    return myData;
    }

}

আমার কোনটি ব্যবহার করা উচিত?


রিফ্লেক্টর গুলি ছোঁড়া সম্পর্কে এবং কিছু আইএল তুলনা করা কীভাবে ;-)।
পপ ক্যাটালিন

6
@ পোপ: সম্পন্ন - আইএল পদগুলিতেও ভাল নয় - কেবল সি # স্টাইল প্রযোজ্য
মার্ক গ্র্যাভেল

1
খুব আকর্ষণীয়, বাহ আমি আজ কিছু শিখি!
পোকাস

উত্তর:


192

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

আইএল মধ্যে পার্থক্য দেখাতে কোড দেয়:

static class Program
{
    static void Main() { }

    static readonly object sync = new object();

    static int GetValue() { return 5; }

    static int ReturnInside()
    {
        lock (sync)
        {
            return GetValue();
        }
    }

    static int ReturnOutside()
    {
        int val;
        lock (sync)
        {
            val = GetValue();
        }
        return val;
    }
}

(মনে রাখবেন যে আমি আনন্দের সাথে তর্ক করতে পারছি ReturnInsideএটি সি # এর একটি সহজ / ক্লিনার বিট)

এবং আইএল (রিলিজ মোড ইত্যাদি) দেখুন:

.method private hidebysig static int32 ReturnInside() cil managed
{
    .maxstack 2
    .locals init (
        [0] int32 CS$1$0000,
        [1] object CS$2$0001)
    L_0000: ldsfld object Program::sync
    L_0005: dup 
    L_0006: stloc.1 
    L_0007: call void [mscorlib]System.Threading.Monitor::Enter(object)
    L_000c: call int32 Program::GetValue()
    L_0011: stloc.0 
    L_0012: leave.s L_001b
    L_0014: ldloc.1 
    L_0015: call void [mscorlib]System.Threading.Monitor::Exit(object)
    L_001a: endfinally 
    L_001b: ldloc.0 
    L_001c: ret 
    .try L_000c to L_0014 finally handler L_0014 to L_001b
} 

method private hidebysig static int32 ReturnOutside() cil managed
{
    .maxstack 2
    .locals init (
        [0] int32 val,
        [1] object CS$2$0000)
    L_0000: ldsfld object Program::sync
    L_0005: dup 
    L_0006: stloc.1 
    L_0007: call void [mscorlib]System.Threading.Monitor::Enter(object)
    L_000c: call int32 Program::GetValue()
    L_0011: stloc.0 
    L_0012: leave.s L_001b
    L_0014: ldloc.1 
    L_0015: call void [mscorlib]System.Threading.Monitor::Exit(object)
    L_001a: endfinally 
    L_001b: ldloc.0 
    L_001c: ret 
    .try L_000c to L_0014 finally handler L_0014 to L_001b
}

সুতরাং আইএল স্তরে তারা [কিছু নাম দিন বা নিন] অভিন্ন (আমি কিছু শিখেছি ;- পি)। এর মতো, একমাত্র বোধগম্য তুলনা হ'ল স্থানীয় কোডিং শৈলীর আইন (অত্যন্ত সাবজেক্টিভ) ... আমি ReturnInsideসরলতার পক্ষে পছন্দ করি তবে আমি কোনওটি নিয়েই আগ্রহী হই না would


15
আমি রেড গেটের (নিখরচায় ও দুর্দান্ত) নেট নেট রিফ্লেক্টর (ছিল: লুটজ রোডার এর নেট নেট রিফ্লেক্টর) ব্যবহার করেছি, তবে আইএলডিএএসএমও তা করবে।
মার্ক গ্র্যাভেল

1
রিফ্লেক্টরের একটি শক্তিশালী দিক হ'ল আপনি নিজের পছন্দসই ভাষায় (সি #, ভিবি, ডেলফি, এমসি ++, ক্রোম ইত্যাদি) আসলে আইএলকে বিচ্ছিন্ন করতে পারেন
মার্ক গ্র্যাভেল

3
আপনার সাধারণ উদাহরণের জন্য আইএল একই থাকে, তবে সম্ভবত আপনি কেবল একটি ধ্রুবক মান ফিরিয়ে দেন ?! আমি বিশ্বাস করি বাস্তব জীবনের পরিস্থিতিগুলির জন্য ফলাফলটি পৃথক হতে পারে এবং সমান্তরাল থ্রেডগুলি একে অপরের জন্য সমস্যাটি ফিরিয়ে আনার আগেই সংশোধন করে সমস্যার কারণ হতে পারে, রিটার্নের স্টেটমেন্টটি লক ব্লকের বাইরে থাকে। বিপজ্জনক!
Torbjørn

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

1
@ রহিল খান না, কেউ নেই; তারা একই. আইএল স্তরে আপনি কোনও অঞ্চলের ভিতরে থাকতে পারবেন নাret.try
মার্ক Gravell

42

এটি কোনও পার্থক্য করে না; তারা উভয়ই একই জিনিস অনুবাদক দ্বারা অনুবাদ করা হয়।

স্পষ্ট করার জন্য, হয় নিম্নলিখিত শব্দার্থবিজ্ঞানের সাথে কার্যকরভাবে অনুবাদ করা হয়েছে:

T myData;
Monitor.Enter(mutex)
try
{
    myData= // something
}
finally
{
    Monitor.Exit(mutex);
}

return myData;

1
ঠিক আছে, চেষ্টাটি সত্যই / অবশেষে - তবে, তালার বাইরের প্রত্যাবর্তনের জন্য এখনও অতিরিক্ত স্থানীয় লোক প্রয়োজন যা এটিকে অপ্টিমাইজ করা যায় না - এবং আরও কোড নেয় ...
মার্ক গ্র্যাভেল

3
আপনি একটি চেষ্টা ব্লক থেকে ফিরে আসতে পারবেন না; এটি অবশ্যই ".leave" অপ-কোড দিয়ে শেষ হবে। সুতরাং নির্গত সিআইএল উভয় ক্ষেত্রে একই হওয়া উচিত।
গ্রেগ বিচ

3
আপনি ঠিক বলেছেন - আমি সবেমাত্র আইএলটির দিকে নজর রেখেছি (আপডেট হওয়া পোস্টটি দেখুন)। আমি কিছু শিখেছি ;
মার্ক

2
কুল, দুর্ভাগ্যবশত আমি যন্ত্রণাদায়ক ঘন্টা থেকে আমার গতিশীল পদ্ধতি :-( লোড করার চেষ্টা ব্লকগুলিতে .ret উপ-কোডগুলি নির্গত বের করার চেষ্টা এবং CLR প্রত্যাখ্যান থাকার শিখেছি
গ্রেগ মধ্যে Beech

আমি সম্পর্ক করতে পারি; আমি যথেষ্ট পরিমাণে প্রতিচ্ছবি করেছি mit আমি কোনও কিছুর বিষয়ে খুব নিশ্চিত না হওয়া পর্যন্ত আমি সি # তে প্রতিনিধি কোডটি লিখি এবং তারপরে আইএলটি দেখি। তবে আপনি অবাক হয়ে কীভাবে আইএল পদে (অর্থাত্ স্ট্যাকটি সিকোয়েন্সিং) করে ভাবতে শুরু করেছেন তা অবাক করার মতো।
মার্ক গ্র্যাভেল

28

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


4
এটি সঠিক, অন্য উত্তরদাতারা অনুপস্থিত বলে মনে হচ্ছে point তাদের তৈরি করা সাধারণ নমুনাগুলি একই আইএল উত্পাদন করতে পারে তবে বেশিরভাগ বাস্তব জীবনের পরিস্থিতিগুলির ক্ষেত্রে এটি এমন নয়।
Torbjørn

4
আমি অন্যান্য উত্তরগুলি সম্পর্কে এ বিষয়ে কথা বলতে অবাক করে
দিয়েছি

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

3
আমি মনে করি না এটি একটি বৈধ পয়েন্ট, কারণ অন্য থ্রেড রিটার্ন কল এবং মূল থ্রেডের চলকটিতে রিটার্ন মানটির আসল অ্যাসাইনমেন্টের মধ্যে মূল্য আপডেট করতে পারে। প্রত্যাবর্তিত মানটি পরিবর্তন করা যায় না বা বর্তমান প্রকৃত মান যেভাবেই হোক তার সাথে সামঞ্জস্যের গ্যারান্টি দেওয়া যায় না। রাইট?
উরো জোকসিমোভিয়

এই উত্তরটি ভুল। অন্য থ্রেড একটি স্থানীয় ভেরিয়েবল পরিবর্তন করতে পারে না। স্থানীয় ভেরিয়েবলগুলি স্ট্যাকের মধ্যে সংরক্ষণ করা হয় এবং প্রতিটি থ্রেডের নিজস্ব স্ট্যাক থাকে। কোনও থ্রেডের স্ট্যাকের ডিফল্ট আকার বিটিডব্লিউটি 1 এমবি
থিওডর জৌলিয়াস

5

এটা নির্ভর করে,

আমি এখানে শস্য বিরুদ্ধে যেতে যাচ্ছি। আমি সাধারণত লকের ভিতরে ফিরে আসতাম।

সাধারণত ভেরিয়েবল মায়াডাটা একটি স্থানীয় ভেরিয়েবল। আমি স্থানীয় ভেরিয়েবলগুলি শুরু করার সময় তাদের ঘোষণার শখ করি। আমার লকের বাইরে আমার রিটার্ন মানটি আরম্ভ করার জন্য খুব কমই আমার কাছে ডেটা থাকে।

সুতরাং আপনার তুলনা আসলে ত্রুটিযুক্ত। আদর্শভাবে দুটি বিকল্পের মধ্যে পার্থক্য যেমনটি আপনি লিখেছিলেন, যা মনে হয় 1 কেসটিকে সম্মতি দেবে, বাস্তবে এটি সামান্য কুরুচিপূর্ণ।

void example() { 
    int myData;
    lock (foo) { 
        myData = ...;
    }
    return myData
}

বনাম

void example() { 
    lock (foo) {
        return ...;
    }
}

আমি কেস 2 পড়ার পক্ষে যথেষ্ট সহজ এবং স্ক্রু আপ করা আরও শক্ত, বিশেষত সংক্ষিপ্ত স্নিপকেটের জন্য find


4

যদি মনে হয় বাহিরের লকটি আরও ভাল দেখাচ্ছে তবে আপনি যদি কোডটি এখানে পরিবর্তন করেন তবে সাবধান হন:

return f(...)

যদি চ (ল) ধরে থাকা লকটি দিয়ে কল করা দরকার তবে অবশ্যই এটি অবশ্যই লকের অভ্যন্তরে থাকা দরকার, যেমন ধারাবাহিকতার জন্য তালার অভ্যন্তরে ফিরে আসা অর্থপূর্ণ হয়।


1

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


0

সহযোগী বিকাশকারীদের কোডটি পড়া সহজ করার জন্য আমি প্রথম বিকল্পটি পরামর্শ দেব।


0

lock() return <expression> সর্বদা বিবৃতি:

1) লক প্রবেশ করুন

2) নির্দিষ্ট ধরণের মানের জন্য স্থানীয় (থ্রেড-নিরাপদ) স্টোর তৈরি করে,

3) স্টোরটি ফেরত মান দিয়ে পূরণ করে <expression>,

4) প্রস্থান লক

5) দোকান ফিরে।

এর অর্থ হ'ল মান, লক স্টেটমেন্ট থেকে ফিরে আসা, ফেরতের আগে সর্বদা "রান্না করা"।

চিন্তা করবেন না lock() return, এখানে কারও কথা শুনবেন না))


-2

দ্রষ্টব্য: আমি এই উত্তরটি সত্যই সঠিক বলে বিশ্বাস করি এবং আমি আশা করি এটিও সহায়ক হবে তবে আমি দৃ concrete় প্রতিক্রিয়ার ভিত্তিতে এটি উন্নত করতে সর্বদা খুশি।

বিদ্যমান উত্তরগুলি সংক্ষিপ্ত করে এবং পরিপূরক করতে:

  • গৃহীত উত্তর শো, যা সিনট্যাক্স ফর্ম নির্বিশেষে আপনি আপনার পছন্দ C # এর , কোড আইএল কোডে - এবং সেইজন্য রানটাইম এ - returnযতক্ষণ না ঘটবে না পরে লক উন্মুক্ত করা হয়েছে।

    • এমনকি স্থাপন যদিও return ভিতরেlock ব্লক অতএব নিয়ন্ত্রণের প্রবাহ, কঠোরভাবে বলতে, মিথ্যাবর্ণন [1] , এটা চিহ্নগুলি সিন্টেক্সের হয় সুবিধাজনক যে এটি একটি-aux-মধ্যে ফেরত মান সঞ্চয় করার জন্য প্রয়োজন obviates। স্থানীয় ভেরিয়েবল (ব্লকের বাইরে ঘোষিত, যাতে এটি returnব্লকের বাইরের সাথে ব্যবহার করা যায় ) - অ্যাডওয়ার্ড কেএমইটিটির উত্তর দেখুন
  • আলাদাভাবে - এবং এই দিক আনুষঙ্গিক প্রশ্নের, কিন্তু এখনও (সুদ হতে পারে রিকার্ডো Villamil এর উত্তর চেষ্টা এটা মোকাবেলার কিন্তু ভুল, আমি মনে করি) - একটি মিশ্রন lockএকটি সঙ্গে বিবৃতি return, অর্থাত্ মান প্রাপ্তির - বিবৃতি returnএকটি ব্লক থেকে রক্ষা করা এ সমবর্তী এক্সেস - শুধুমাত্র অর্থপূর্ণ "রক্ষা করে" ফিরে মান আহ্বানকারী সুযোগ 'র যদি এটা আসলে প্রয়োজন একবার প্রাপ্ত না রক্ষা নেই , নিম্নলিখিত পরিস্থিতিতে প্রযোজ্য যা:

    • যদি প্রত্যাবর্তিত মান কোনও সংগ্রহ থেকে এমন একটি উপাদান থাকে যা কেবলমাত্র উপাদানগুলিকে সংযোজন এবং অপসারণের ক্ষেত্রে সুরক্ষার প্রয়োজন হয়, উপাদানগুলি নিজের এবং / অথবা পরিবর্তনের ক্ষেত্রে নয় ...

    • ... যদি মান ফেরত দেওয়া হয় তবে এটি কোনও মান ধরণের বা স্ট্রিংয়ের উদাহরণ ।

      • দ্রষ্টব্য যে এক্ষেত্রে কলার মানটির একটি স্ন্যাপশট (অনুলিপি) [২] পান - যা কলকারী ততক্ষণে এটি পরীক্ষা করে এটি আরসের উত্সের ডেটা কাঠামোর বর্তমান মান হতে পারে না।
    • অন্য কোনও ক্ষেত্রে, লকিং পদ্ধতিটির ভিতরে (কেবল) নয়, কলার দ্বারা সম্পাদন করা উচিত ।


[1] থিওডর Zoulias তুলে ধরে যে টেকনিক্যালি স্থাপন জন্য সত্য returnভিতরে try, catch, using, if, while, for, ... বিবৃতি; তবে এটি এর নির্দিষ্ট উদ্দেশ্যlock বিবৃতিটির যা প্রকৃত নিয়ন্ত্রণ প্রবাহের তদন্তকে আমন্ত্রণ জানাতে পারে, যেমনটি এই প্রশ্নটি জিজ্ঞাসা করা হয়েছে এবং অনেক মনোযোগ পেয়েছে তার প্রমাণ হিসাবে।

[2] একটি মান-ধরণের দৃষ্টান্ত অ্যাক্সেস অবিচ্ছিন্নভাবে একটি থ্রেড-স্থানীয় তৈরি করে, এটির অন-স্ট্যাক অনুলিপি; স্ট্রিংগুলি প্রযুক্তিগতভাবে রেফারেন্স-টাইপ দৃষ্টান্তযুক্ত হলেও, তারা কার্যকরভাবে পছন্দ মতো-জাতীয় ধরণের দৃষ্টান্তগুলি ব্যবহার করে।


আপনার উত্তরের বর্তমান অবস্থা (পুনর্বিবেশন ১৩) সম্পর্কে আপনি এখনও অস্তিত্বের কারণগুলির সম্পর্কে অনুমান করছেন lockএবং রিটার্নের বিবৃতি স্থাপনের অর্থটি পেয়েছেন। এই প্রশ্নটি আইএমএইচও সম্পর্কিত নয় এমন একটি আলোচনা। এছাড়াও আমি "ভুল উপস্থাপন" এর ব্যবহারকে বেশ বিঘ্নিত মনে করি। একটি থেকে ফিরে যদি lockমিথ্যাবর্ণন নিয়ন্ত্রণের প্রবাহ, তারপর একই A থেকে ফেরার বলেছেন হতে পারে try, catch, using, if, while, for, এবং ভাষা অন্য কোন কনস্ট্রাক্ট। এটি বলার মতো যে সি # নিয়ন্ত্রণ প্রবাহের ভুল উপস্থাপনায় ছাঁটাইয়াছে। যীশু ...
থিওডর জোলিয়াস

"এটি বলার মতো যে সি # নিয়ন্ত্রণ প্রবাহের ভুল উপস্থাপনায় ছাঁটাইয়াছে" - ওয়েল, এটি প্রযুক্তিগতভাবে সত্য, এবং "ভুল উপস্থাপনা" শব্দটি কেবলমাত্র সেভাবে নেওয়া বেছে নেওয়া হলে একটি মূল্য বিচার value সহ try,, if... আমি ব্যক্তিগতভাবে এটি সম্পর্কে ভাবার প্রবণতাও করি না, তবে lockবিশেষত, আমার প্রসঙ্গে প্রশ্নটি উত্থাপিত হয়েছিল - এবং যদি এটি অন্যদের জন্যও না উত্থাপিত হয় তবে এই প্রশ্নটি কখনই জিজ্ঞাসা করা হত না , এবং গ্রহণযোগ্য উত্তরটি সত্য আচরণটি তদন্ত করতে খুব বেশি পরিমাণে যায় নি।
mklement0
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.