বনাম রেফ বনাম বাইরে কখন ব্যবহার করবেন


383

অন্য কেউ যখন আমাকে জিজ্ঞাসা করেছিলেন যে তাদের outপরিবর্তে প্যারামিটার কীওয়ার্ডটি ব্যবহার করা উচিত ref। আমি (আমি মনে করি) refএবং outকীওয়ার্ডগুলির মধ্যে পার্থক্য বুঝতে পেরেছি (যা আগে জিজ্ঞাসা করা হয়েছিল ) এবং সর্বোত্তম ব্যাখ্যাটি মনে হয় যে ref== inএবং out, এমন কয়েকটি (অনুমান বা কোড) উদাহরণ যেখানে আমার সর্বদা ব্যবহার করা উচিত outএবং না ref

যেহেতু refআরও সাধারণ, আপনি কেন কখনও ব্যবহার করতে চান out? এটি কি কেবল সিনট্যাকটিক চিনি?


18
ব্যবহারে পাস করা একটি পরিবর্তনশীল outএটি বরাদ্দ করার আগে থেকে পড়া যায় না। refএই সীমাবদ্ধতা নেই। সুতরাং যে আছে।
কোরি ওগবার্ন

17
সংক্ষেপে, refআউট / আউট এর জন্য, যখন outকেবল বহির্মুখী প্যারামিটার।
টিম এস

3
আপনি ঠিক কি পাবেন না?
tnw

4
এছাড়াও outভেরিয়েবলগুলি ফাংশনে নির্ধারিত হতে হবে।
কোরি ওগবার্ন

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

উত্তর:


399

outআপনার প্রয়োজন না হলে আপনার ব্যবহার করা উচিত ref

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

এর বাইরে এটি ঘোষণাপত্রের পাঠক বা কলটিকেও দেখায় যে প্রাথমিক মান প্রাসঙ্গিক (এবং সম্ভাব্যভাবে সংরক্ষিত), অথবা ফেলে দেওয়া হয়েছে কিনা।

একটি সামান্য পার্থক্য হিসাবে, একটি আউট প্যারামিটার আরম্ভ করা প্রয়োজন।

উদাহরণস্বরূপ out:

string a, b;
person.GetBothNames(out a, out b);

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

string a = String.Empty, b = String.Empty;
person.GetBothNames(ref a, ref b);

পাঠকদের বিভ্রান্ত করতে পারে, কারণ দেখে মনে হচ্ছে যে ক এবং খ এর প্রাথমিক মানগুলি প্রাসঙ্গিক (যদিও পদ্ধতির নামটি ইঙ্গিত দেয় যে তারা তা নয়)।

উদাহরণস্বরূপ ref:

string name = textbox.Text;
bool didModify = validator.SuggestValidName(ref name);

এখানে প্রাথমিক মান পদ্ধতির সাথে প্রাসঙ্গিক।


5
"আসলেই তা হয় না।" - আপনি কি বলতে চান দয়া করে আরও ভাল করে বলতে পারেন?
পিটারচেন 8

3
আপনি refডিফল্ট মানগুলির জন্য ব্যবহার করতে চান না ।
সি। এভেনহুইস

155
উত্তরোত্তর জন্য: অন্য একটি পার্থক্য অন্য কেউ উল্লেখ করেছেন বলে মনে হয় না, যেমন এখানে বলা হয়েছে ; একটি outপ্যারামিটারের জন্য, পদ্ধতিটি ফেরার আগে কলিং পদ্ধতির একটি মান নির্ধারণ করা প্রয়োজন- আপনি না আছে একটি সুত্র প্যারামিটার নিয়ে কিছু করতে।
brichins

3
@ ব্রিচিনস দয়া করে আপনার উল্লিখিত লিঙ্কে 'মন্তব্য (সম্প্রদায় সংযোজন)' বিভাগটি দেখুন । এটি একটি ত্রুটি যা ভিএস ২০০৮ ডকুমেন্টেশনে সংশোধন করা হয়েছে।
ভারত রাম ভি

13
@ ব্র্যাচিংস নামক পদ্ধতিটি কলিং পদ্ধতি নয়, একটি মান নির্ধারণ করা প্রয়োজন। zverev.eugene এটিই VS 2008 ডকুমেন্টেশনে সংশোধন করা হয়েছিল।
সেগফল্ট

72

পরামিতি ব্যবহার করা হচ্ছে না তা বোঝাতে ব্যবহার করুন, কেবল সেট করুন। এটি কলারটিকে বুঝতে সাহায্য করে যে আপনি সর্বদা প্যারামিটারটি আরম্ভ করছেন।

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


3
+1 আমি জানতাম না যে এটি খুব রেফারেন্স ধরণের জন্যও ব্যবহার করা যেতে পারে, সুন্দর পরিষ্কার উত্তর, ধন্যবাদ
ডেল

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

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

2
@ ดาว: এটি রেফারেন্স প্রকারের সাথে ব্যবহার করা যেতে পারে কারণ আপনি যখন কোনও রেফারেন্স টাইপ প্যারামিটারে পাস করেন তখন আপনি যা যাচ্ছেন তা হ'ল রেফারেন্সের মানটি নিজেই নয় itself সুতরাং এটি এখনও পাস-বাই-মান।
তারিক

38

আপনি এর মধ্যে সঠিক, শব্দার্থক্রমে, ref"ইন" এবং "আউট" কার্যকারিতা উভয়ই সরবরাহ করে, যেখানে outকেবল "আউট" কার্যকারিতা সরবরাহ করে। কিছু বিষয় বিবেচনা করার আছে:

  1. outপদ্ধতিটি প্রয়োজন যে পরামিতিটি গ্রহণ করা আবশ্যক, ফিরে আসার আগে এক পর্যায়ে, ভেরিয়েবলের জন্য একটি মান নির্ধারণ করুন। আপনি এই প্যাটার্নটি কিছু কী / মান ডেটা স্টোরেজ শ্রেণীর মতো দেখতে পাবেন Dictionary<K,V>যেখানে আপনার মতো ফাংশন রয়েছে TryGetValue। এই ফাংশনটি এমন একটি outপ্যারামিটার নিয়ে থাকে যা পুনরুদ্ধার করা হলে মানটি কী হবে তা ধারণ করে। এটা তোলে আহ্বানকারী একটি মান পাস করার জন্য অর্থে দেখা যায় না হবে মধ্যে এই ফাংশন, তাই outগ্যারান্টি করতে ব্যবহৃত হয় যে কিছু মান কল পর পরিবর্তনশীল থাকবে, যদিও তা "বাস্তব" ডেটা নয় (ক্ষেত্রে TryGetValueযেখানে কীটি উপস্থিত নেই)।
  2. outrefইন্টারপ কোড নিয়ে কাজ করার সময় এবং প্যারামিটারগুলি আলাদাভাবে মার্শাল করা হয়

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

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


1
নোট করুন যে আউটপুট প্যারামিটারের জন্য ডাকা পদ্ধতিটি একটি প্রয়োজনীয় মূল্য নির্ধারণ করে তা সি # সংকলক দ্বারা প্রয়োগ করা হয়, অন্তর্নিহিত আইএল দ্বারা নয়। সুতরাং, ভিবি.নেটে লিখিত একটি গ্রন্থাগার convention সম্মেলনের সাথে সামঞ্জস্য হতে পারে না।
jmoreno

রেফার মতো শব্দগুলি আসলে সি ++ (*) এর ডেরেফারেন্সিং প্রতীকটির সমতুল্য। সি # তে পাসবিবি রেফারেন্স অবশ্যই সি / সি ++ এর সাথে ডাবল পয়েন্টার (পয়েন্টারকে নির্দেশক) হিসাবে বোঝায় তাই রেফটিকে অবশ্যই 1 ম পয়েন্টারকে অবলম্বন করতে হবে, প্রেক্ষাপটে প্রকৃত অবজেক্টের মেমরির অবস্থানের জন্য পদ্ধতিটি অ্যাক্সেসের অনুমতি দেয়।
আসুন

আমি আসলে একটি সঠিক পরামর্শ দেবো এবং কীটি খুঁজে না পাওয়ার ক্ষেত্রে স্পষ্টভাবে না TryGetValueব্যবহার করব refnot out
নেটমেজ

27

এটি সংকলন প্রসঙ্গে (নীচের উদাহরণ দেখুন) উপর নির্ভর করে।

outএবং refউভয়ই রেফারেন্সের মাধ্যমে ভেরিয়েবল পাসিংকে বোঝায়, তবুও refপাস করার আগে ভেরিয়েবলটি আরম্ভ করা দরকার, যা মার্শালিংয়ের প্রসঙ্গে একটি গুরুত্বপূর্ণ পার্থক্য হতে পারে (আন্তঃ: UmanagedToManagedTransition বা বিপরীতে)

এমএসডিএন সতর্ক করেছে :

রেফারেন্স ধরণের ধারণার সাথে রেফারেন্স দিয়ে পাস করার ধারণাটিকে বিভ্রান্ত করবেন না। দুটি ধারণা এক নয়। কোনও পদ্ধতির পরামিতি মান মান বা রেফারেন্স টাইপ নির্বিশেষে রেফ দ্বারা সংশোধন করা যেতে পারে। রেফারেন্স দ্বারা পাস করার সময় কোনও মান ধরণের বক্সিং নেই।

অফিসিয়াল এমএসডিএন ডক্স থেকে:

আউট কীওয়ার্ডের কারণে যুক্তিগুলি রেফারেন্সের মাধ্যমে পাস হয়। এটি রেফ কীওয়ার্ডের মতো, রেফের ব্যতীত চলকটি পাস করার আগে আরম্ভ করা দরকার initial

রেফ কীওয়ার্ডটি একটি আর্গুমেন্টকে মান দ্বারা নয়, রেফারেন্স দ্বারা পাস করার কারণ করে। রেফারেন্স দ্বারা পাস করার প্রভাবটি হল যে পদ্ধতিতে পরামিতিগুলির কোনও পরিবর্তন কলিং পদ্ধতিতে অন্তর্নিহিত আর্গুমেন্ট ভেরিয়েবলের প্রতিফলিত হয়। একটি রেফারেন্স প্যারামিটারের মান সর্বদা অন্তর্নিহিত আর্গুমেন্ট ভেরিয়েবলের মান হিসাবে সমান।

যুক্তি নির্ধারিত হয়ে গেলে আমরা যাচাই করতে পারি যে আউট এবং রেফ প্রকৃতপক্ষে একই:

সিআইএল উদাহরণ :

নিম্নলিখিত উদাহরণ বিবেচনা করুন

static class outRefTest{
    public static int myfunc(int x){x=0; return x; }
    public static void myfuncOut(out int x){x=0;}
    public static void myfuncRef(ref int x){x=0;}
    public static void myfuncRefEmpty(ref int x){}
    // Define other methods and classes here
}

সিআইএল-তে, নির্দেশাবলী myfuncOutএবং myfuncRefপ্রত্যাশার মতো অভিন্ন and

outRefTest.myfunc:
IL_0000:  nop         
IL_0001:  ldc.i4.0    
IL_0002:  starg.s     00 
IL_0004:  ldarg.0     
IL_0005:  stloc.0     
IL_0006:  br.s        IL_0008
IL_0008:  ldloc.0     
IL_0009:  ret         

outRefTest.myfuncOut:
IL_0000:  nop         
IL_0001:  ldarg.0     
IL_0002:  ldc.i4.0    
IL_0003:  stind.i4    
IL_0004:  ret         

outRefTest.myfuncRef:
IL_0000:  nop         
IL_0001:  ldarg.0     
IL_0002:  ldc.i4.0    
IL_0003:  stind.i4    
IL_0004:  ret         

outRefTest.myfuncRefEmpty:
IL_0000:  nop         
IL_0001:  ret         

নোপ : কোনও অপারেশন নয়, এলডিএলক : স্থানীয় লোড করুন, স্টলোক : স্ট্যাক লোকাল, লিডারগ : লোড আর্গুমেন্ট, বিএস.এস : লক্ষ্যবস্তু করার জন্য শাখা ....

(দেখুন: সিআইএল নির্দেশাবলীর তালিকা )


23

নীচে কিছু নোট রয়েছে যা আমি সি # আউট ভিএস রেফার উপর এই কোডড্রজেক্ট নিবন্ধ থেকে টেনেছি

  1. এটি কেবল তখনই ব্যবহার করা উচিত যখন আমরা কোনও ফাংশন বা কোনও পদ্ধতি থেকে একাধিক আউটপুট আশা করি। কাঠামোগুলি সম্পর্কে চিন্তাভাবনাও এর জন্য একটি ভাল বিকল্প হতে পারে।
  2. আরএফ এবং আউট হ'ল এমন কীওয়ার্ড যা নির্দেশ করে যে কীভাবে ডেটা কলার থেকে কলি হয়ে যায় এবং বিপরীতে।
  3. আরএফ-তে ডেটা দুই দিক দিয়ে যায়। কলার থেকে কলি এবং তদ্বিপরীত।
  4. আউট ইন ডেটা কলি থেকে কলার পর্যন্ত কেবল একটি পথ অতিক্রম করে। এই ক্ষেত্রে যদি কলার কলিকে ডেটা প্রেরণ করার চেষ্টা করে তবে তা অগ্রাহ্য / প্রত্যাখ্যাত হবে।

আপনি যদি ভিজ্যুয়াল ব্যক্তি হন তবে দয়া করে এই আপনার ইউটিউব ভিডিওটি দেখুন যা ব্যবহারিকভাবে পার্থক্যটি প্রকাশ করে https://www.youtube.com/watch?v=lYdcY5zulXA

চিত্রের নীচে পার্থক্যগুলি আরও চাক্ষুষভাবে দেখায়

সি # আউট বনাম রেফারেন্স


1
one-way, two-wayপদ এখানে অপব্যবহার হতে পারে। এগুলি আসলে উভয় পক্ষের, তবে তাদের ধারণাগত আচরণগুলি পরামিতিগুলির রেফারেন্স এবং মানগুলির সাথে পৃথক রয়েছে
ইবুবি

17

আপনি refযদি প্যারামিটারটি পড়তে এবং লিখতে চান তবে আপনাকে ব্যবহার করা দরকার । আপনি outযদি কেবল লেখার পরিকল্পনা করেন তবে আপনাকে ব্যবহার করা দরকার । বাস্তবে, outযখন আপনার একাধিক রিটার্ন মান প্রয়োজন হয় বা যখন আপনি আউটপুট জন্য সাধারণ রিটার্ন মেকানিজম ব্যবহার করতে চান না তখন (তবে এটি বিরল হওয়া উচিত) is

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

int x;
Foo(ref x); // error: x is uninitialized

void Bar(out int x) {}  // error: x was not written to

উদাহরণস্বরূপ, int.TryParseএকটি প্রদান করে boolএবং একটি out intপরামিতি গ্রহণ করে :

int value;
if (int.TryParse(numericString, out value))
{
    /* numericString was parsed into value, now do stuff */
}
else
{
    /* numericString couldn't be parsed */
}

এটি এমন পরিস্থিতির একটি স্পষ্ট উদাহরণ যেখানে আপনাকে দুটি মান আউটপুট করতে হবে: সংখ্যার ফলাফল এবং রূপান্তরটি সফল হয়েছিল কি না। সিএলআর এর লেখকরা outএখানে নির্বাচন করার সিদ্ধান্ত নিয়েছে কারণ তারা intআগে কী হতে পারে সে বিষয়ে তাদের কোন চিন্তা নেই ।

জন্য ref, আপনি তাকান করতে পারেন Interlocked.Increment:

int x = 4;
Interlocked.Increment(ref x);

Interlocked.Incrementপারমাণবিকরূপে এর মান বৃদ্ধি করে x। যেহেতু আপনাকে xএটি বাড়ানোর জন্য পড়তে হবে, এটি এমন পরিস্থিতি যেখানে refআরও উপযুক্ত। আপনি সম্পূর্ণরূপে এটি যত্ন xনেওয়ার আগে যা ছিল তা যত্নশীল Increment

সি # এর পরবর্তী সংস্করণে outপ্যারামিটারগুলিতে পরিবর্তনশীল ঘোষণা করাও সম্ভব হবে , কেবলমাত্র তাদের আউটপুট-প্রকৃতির উপরে আরও জোর দেওয়া:

if (int.TryParse(numericString, out int value))
{
    // 'value' exists and was declared in the `if` statement
}
else
{
    // conversion didn't work, 'value' doesn't exist here
}

আপনার প্রতিক্রিয়া জন্য জিনাক ধন্যবাদ। তবে আপনি কি আমাকে ব্যাখ্যা করতে পারেন যে আমি কেন প্যারামিটারটি পড়তে এবং লিখতে ব্যবহার করতে পারি না?
রাজবীর সিং

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

জিনাক, আমি আপনার সাথে একমত। তবে নীচের উদাহরণে একটি আউট প্যারামিটার পড়া ও লেখার জন্য ব্যবহার করা যেতে পারে: স্ট্রিং নাম = "মাইনেম"; ব্যক্তিগত অকার্যকর আউটমেথোদ (আউট স্ট্রিং নেম আউট) {if (nameOut == "myName") {nameOut = "রাজবীর সিং আউট পদ্ধতিতে"; }}
রাজবীর সিং

1
@ রাজবীরসিংহ, আপনার উদাহরণ সংকলন করে না। আপনি nameOutআপনার ifবিবৃতিতে পড়তে পারবেন না কারণ এটি আগে কিছু বরাদ্দ করা হয়নি।
জিনাক

ধন্যবাদ @ জেনাক তুমি একদম সঠিক. এটি সংকলন করে না আমার সহায়তার জন্য অনেক ধন্যবাদ এবং এখন এটি আমার কাছে বোধগম্য :)
রাজবীর সিং

7

outএর আরও সীমাবদ্ধ সংস্করণ ref

কোনও পদ্ধতিতে, outপদ্ধতিটি ছাড়ার আগে আপনাকে সমস্ত পরামিতিগুলি বরাদ্দ করতে হবে । এছাড়াও একটি outপ্যারামিটারে নির্ধারিত মানগুলি উপেক্ষা করা হয়, যেখানে refতাদের নির্ধারিত হওয়া প্রয়োজন।

সুতরাং outআপনাকে করতে দেয়:

int a, b, c = foo(out a, out b);

যেখানে refএকটি এবং বি নিয়োগ করা দরকার।


যদি কিছু outহয় তবে কম সীমাবদ্ধ সংস্করণ। ref"পূর্বশর্ত: পরিবর্তনশীল অবশ্যই নির্ধারিত, পোস্টকন্ডিশন: পরিবর্তনশীল অবশ্যই নির্ধারিত হয়", যখন outকেবলমাত্র `পোস্টকন্ডিশন: পরিবর্তনশীল অবশ্যই নির্ধারিত হয়"। (এবং প্রত্যাশার হিসাবে, আরও কম পূর্বশর্ত সহ একটি ফাংশন বাস্তবায়নের জন্য আরও প্রয়োজন)
বেন ভয়েগ্ট

@ বেনভয়েগ: অনুমান করুন যে আপনি কোন দিকে তাকিয়েছেন তা নির্ভর করে :) আমি মনে করি কোডিং নমনীয়তার (?) শর্তে আমি প্রতিবন্ধকতা বোঝাতে চাইছি।
লেপি

7

এটা কিভাবে ধ্বনি:

আউট = শুধুমাত্র আরম্ভ / একটি প্যারামিটার (প্যারামিটার খালি হতে হবে) তা ফেরত পূরণ আউট প্লেইন

সুত্র = রেফারেন্স, মান প্যারামিটার (হয়তো মান), কিন্তু ফাংশন এটা modifiy পারবেন না।


আউট প্যারামিটার ভেরিয়েবল একটি পদ্ধতিতে এটি পাস করার আগে একটি মান পেতে পারে।
বেনস ভিগার্ট

6

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

outশব্দ কারণ আর্গুমেন্ট রেফারেন্স দ্বারা পাস করতে হবে। এটি কীওয়ার্ডের মতো ref, ব্যতীত refভেরিয়েবলটি পাস হওয়ার আগেই আরম্ভ করা দরকার। একটি outপ্যারামিটার ব্যবহার করতে , পদ্ধতির সংজ্ঞা এবং কলিং পদ্ধতি উভয়ের অবশ্যই স্পষ্টভাবে outকীওয়ার্ডটি ব্যবহার করা উচিত । উদাহরণস্বরূপ: সি #

class OutExample
{
    static void Method(out int i)
    {
        i = 44;
    }
    static void Main()
    {
        int value;
        Method(out value);
        // value is now 44
    }
}

যদিও outআর্গুমেন্ট হিসাবে ভেরিয়েবলগুলি পাস করার আগে পাস করার আগে আরম্ভ করা উচিত নয়, তথাকথিত পদ্ধতিটি ফিরে আসার আগে একটি মান নির্ধারণ করা প্রয়োজন।

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

class CS0663_Example
{
    // Compiler error CS0663: "Cannot define overloaded 
    // methods that differ only on ref and out".
    public void SampleMethod(out int i) { }
    public void SampleMethod(ref int i) { }
}

ওভারলোডিং করা যায়, তবে, যদি একটি পদ্ধতি একটি refবা outযুক্তি নেয় এবং অন্যটি এর মতো ব্যবহার করে না: সি #

class OutOverloadExample
{
    public void SampleMethod(int i) { }
    public void SampleMethod(out int i) { i = 5; }
}

বৈশিষ্ট্যগুলি ভেরিয়েবল নয় এবং তাই outপরামিতি হিসাবে পাস করা যায় না ।

অ্যারে পাস করার বিষয়ে তথ্যের জন্য, অ্যারে ব্যবহার করে refএবং out(সি # প্রোগ্রামিং গাইড) দেখুন।

আপনি ব্যবহার করতে পারবেন না refএবং outপদ্ধতি নিম্নলিখিত ধরণের জন্য এখানে:

Async methods, which you define by using the async modifier.

Iterator methods, which include a yield return or yield break statement.

উদাহরণ

outআপনি একাধিক মান ফিরিয়ে দিতে কোনও পদ্ধতি চাইলে কোনও পদ্ধতি ঘোষণা করা কার্যকর। নিম্নলিখিত উদাহরণটি outএকক পদ্ধতিতে কল দিয়ে তিনটি ভেরিয়েবল ফেরত দেয়। মনে রাখবেন যে তৃতীয় যুক্তি নালকে বরাদ্দ করা হয়েছে। এটি বিকল্পগুলিকে মানগুলি ফিরিয়ে আনতে সক্ষম করে। সি শার্প

class OutReturnExample
{
    static void Method(out int i, out string s1, out string s2)
    {
        i = 44;
        s1 = "I've been returned";
        s2 = null;
    }
    static void Main()
    {
        int value;
        string str1, str2;
        Method(out value, out str1, out str2);
        // value is now 44
        // str1 is now "I've been returned"
        // str2 is (still) null;
    }
}

6

কিভাবে ব্যবহার inবা outবা refC #?

  • সমস্ত কীওয়ার্ডের C#একই কার্যকারিতা রয়েছে তবে কিছু সীমা রয়েছে
  • in কলিত পদ্ধতিতে যুক্তিগুলি সংশোধন করা যায় না।
  • ref যুক্তি সংশোধন করা যেতে পারে।
  • ref কলার ব্যবহারের আগে অবশ্যই এটি আরম্ভ করা উচিত এটি পদ্ধতিতে পড়া এবং আপডেট করা যেতে পারে।
  • out কলকারী দ্বারা যুক্তিগুলি অবশ্যই সংশোধন করতে হবে।
  • out তর্কগুলি পদ্ধতিতে শুরু করতে হবে
  • তাত্ক্ষণিক হিসাবে প্রেরণযোগ্য ভেরিয়েবলগুলিin কোনও পদ্ধতিতে কল করার আগে আর্গুমেন্টটি শুরু করতে হবে। তবে, বলা পদ্ধতিটি কোনও মান নির্ধারণ করতে পারে না বা যুক্তিটি সংশোধন করতে পারে।

আপনি ব্যবহার করতে পারবেন না in, refএবং outপদ্ধতি নিম্নলিখিত ধরণের জন্য এখানে:

  • অ্যাসিঙ্ক পদ্ধতিগুলি , যা আপনি asyncসংশোধক ব্যবহার করে সংজ্ঞায়িত করেন ।
  • Iterator পদ্ধতি , যা একটি yield returnবা yield breakবিবৃতি অন্তর্ভুক্ত ।

5

কেবল ওপি-র মন্তব্যে স্পষ্ট করেই বলা যায় যে রেফ এবং আউটতে ব্যবহার হ'ল "পদ্ধতির বাইরে ঘোষিত কোনও মান ধরণের বা কাঠামোর উল্লেখ", যা ইতিমধ্যে ভুলতে প্রতিষ্ঠিত হয়েছে।

স্ট্রিংবিল্ডারে রেফের ব্যবহারটি বিবেচনা করুন, এটি একটি রেফারেন্স টাইপ:

private void Nullify(StringBuilder sb, string message)
{
    sb.Append(message);
    sb = null;
}

// -- snip --

StringBuilder sb = new StringBuilder();
string message = "Hi Guy";
Nullify(sb, message);
System.Console.WriteLine(sb.ToString());

// Output
// Hi Guy

যেমনটি প্রয়োগ হয়েছে:

private void Nullify(ref StringBuilder sb, string message)
{
    sb.Append(message);
    sb = null;
}

// -- snip --

StringBuilder sb = new StringBuilder();
string message = "Hi Guy";
Nullify(ref sb, message);
System.Console.WriteLine(sb.ToString());

// Output
// NullReferenceException

4

রেফ হিসাবে পাস একটি আর্গুমেন্ট পদ্ধতিতে পাস করার আগে আরম্ভ করা উচিত যখন কোনও পদ্ধতিতে পাস করার আগে আউট প্যারামিটারটি আরম্ভ করার প্রয়োজন হয় না।


4

আপনি কেন কখনও ব্যবহার করতে চান?

অন্যদের জানতে দেওয়ার জন্য যে পরিবর্তনশীলটি যখন ডাকা পদ্ধতি থেকে ফিরে আসে তখন আরম্ভ করা হবে!

উপরে উল্লিখিত হিসাবে: "আউট প্যারামিটারের জন্য, পদ্ধতিটি ফেরার আগে কলিং পদ্ধতিতে একটি মান নির্ধারণ করা প্রয়োজন " "

উদাহরণ:

Car car;
SetUpCar(out car);
car.drive();  // You know car is initialized.

4

মূলত উভয় refএবং outপদ্ধতির মধ্যে অবজেক্ট / মান পাস করার জন্য

আউট কীওয়ার্ডের কারণে যুক্তিগুলি রেফারেন্সের মাধ্যমে পাস হয়। এটি রেফ কীওয়ার্ডের মতো, রেফের ব্যতীত ভেরিয়েবলটি পাস হওয়ার আগেই আরম্ভ করা দরকার।

out : আর্গুমেন্টটি আরম্ভ হয় না এবং এটি পদ্ধতিতে শুরু করতে হবে

ref : তর্কটি ইতিমধ্যে শুরু করা হয়েছে এবং এটি পদ্ধতিতে পড়া এবং আপডেট করা যেতে পারে।

রেফারেন্স-ধরণের জন্য "রেফ" ব্যবহার কী?

আপনি প্রদত্ত রেফারেন্সটি অন্য একটি উদাহরণে পরিবর্তন করতে পারেন।

তুমি কি জানতে?

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

  2. নিম্নলিখিত ধরণের পদ্ধতির জন্য আপনি রেফ এবং আউট কীওয়ার্ড ব্যবহার করতে পারবেন না:

    • অ্যাসিঙ্ক পদ্ধতিগুলি, যা আপনি অ্যাসিঙ্ক পরিবর্তক ব্যবহার করে সংজ্ঞায়িত করেন।
    • আইট্রেটার পদ্ধতিগুলি, যার মধ্যে একটি ফলন ফেরত বা ফলন বিরতি বিবৃতি অন্তর্ভুক্ত।
  3. বৈশিষ্ট্যগুলি ভেরিয়েবল নয় এবং তাই পরামিতিগুলির হিসাবে পাস করা যায় না।


4

সি # 7 সম্পর্কিত অতিরিক্ত নোট:
সি # 7 এ ভেরিয়েবলগুলি ব্যবহার করে পূর্বনির্ধারিত হওয়ার দরকার নেই। সুতরাং এর মতো একটি কোড:

public void PrintCoordinates(Point p)
{
  int x, y; // have to "predeclare"
  p.GetCoordinates(out x, out y);
  WriteLine($"({x}, {y})");
}

এভাবে লেখা যেতে পারে:

public void PrintCoordinates(Point p)
{
  p.GetCoordinates(out int x, out int y);
  WriteLine($"({x}, {y})");
}

উত্স: সি # 7 এ নতুন কী।


4

এখনও একটি ভাল সংক্ষিপ্তসার প্রয়োজন অনুভব করুন, এটিই আমি এনেছি।

সারসংক্ষেপ,

যখন আমরা ফাংশনের অভ্যন্তরে থাকি তখন এইভাবে আমরা ভেরিয়েবল ডেটা অ্যাক্সেস নিয়ন্ত্রণ নির্দিষ্ট করি ,

in = আর

out = অবশ্যই আর এর আগে ডাব্লু

ref = আর + ডাব্লু


ব্যাখ্যা,

in

ফাংশন শুধুমাত্র পারে পড়ুন যে পরিবর্তনশীল।

out

চলক প্রথম কারণ ইনিশিয়ালাইজ করা আবশ্যক,
ফাংশন আবশ্যক লিখুন আগে এটি পড়ুন

ref

ফাংশনটি সেই পরিবর্তনশীলটিতে পড়তে / লিখতে পারে।


কেন এর নামকরণ করা হয়েছে?

যেখানে ডেটা সংশোধন করা হবে সেদিকে দৃষ্টি নিবদ্ধ করা,

in

ফাংশন (ইন) প্রবেশের আগে কেবল ডেটা সেট করতে হবে।

out

ফাংশন ছাড়ার আগে কেবলমাত্র ডেটা সেট করতে হবে।

ref

(ইন) ফাংশনে প্রবেশের আগে ডেটা সেট করতে হবে।
ফাংশন ছাড়ার আগে ডেটা সেট করা যেতে পারে।


হতে পারে (ইন / আউট / রেফ) এর নাম পরিবর্তন করে (আর / সিআর / আরডাব্লু) করা উচিত। বা নাও হতে পারে, ইন / আউট একটি উত্তম রূপক।
টিঙ্কার

0

এটি লক্ষ করা উচিত যে inএটি সি # Ver 7.2 হিসাবে একটি বৈধ কীওয়ার্ড :

ইন প্যারামিটার সংশোধক সি # 7.2 এবং তার পরে পাওয়া যাবে। পূর্ববর্তী সংস্করণগুলি সংকলক ত্রুটি জেনারেট করে CS8107 ("বৈশিষ্ট্য 'কেবলমাত্র পঠনযোগ্য রেফারেন্স' সি # 7.0-এ উপলব্ধ নয় Please দয়া করে ভাষা সংস্করণ .2.২ বা তার বেশি ব্যবহার করুন।") সংকলক ভাষার সংস্করণটি কনফিগার করতে দেখুন, সি # ভাষার সংস্করণ নির্বাচন করুন।

...

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

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