কোনও বস্তু পাস করার সময় 'রেফ' কীওয়ার্ডটি কেন ব্যবহার করবেন?


290

আমি যদি কোনও পদ্ধতিতে কোনও বস্তুটি পাস করছি তবে আমি কেন রেফার শব্দটি ব্যবহার করব? এটি কি কোনওভাবেই ডিফল্ট আচরণ নয়?

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

class Program
{
    static void Main(string[] args)
    {
        TestRef t = new TestRef();
        t.Something = "Foo";

        DoSomething(t);
        Console.WriteLine(t.Something);
    }

    static public void DoSomething(TestRef t)
    {
        t.Something = "Bar";
    }
}


public class TestRef
{
    public string Something { get; set; }
}

আউটপুটটি "বার" যার অর্থ অবজেক্টটি একটি রেফারেন্স হিসাবে পাস হয়েছিল।

উত্তর:


298

refআপনি যদি বস্তুটি কী তা পরিবর্তন করতে চান তবে পাস করুন :

TestRef t = new TestRef();
t.Something = "Foo";
DoSomething(ref t);

void DoSomething(ref TestRef t)
{
  t = new TestRef();
  t.Something = "Not just a changed t, but a completely different TestRef object";
}

ডসোমিংথিংয়ের পরে, মূলটিকে tউল্লেখ করে না new TestRef, তবে সম্পূর্ণ ভিন্ন একটি বিষয়কে বোঝায়।

আপনি যদি কোনও অপরিবর্তনীয় বস্তুর মান পরিবর্তন করতে চান তবে এটি কার্যকরও হতে পারে, যেমন ক stringstringএকবার তৈরি হয়ে গেলে এর মান আপনি পরিবর্তন করতে পারবেন না । তবে একটি ব্যবহার করে refআপনি এমন একটি ফাংশন তৈরি করতে পারেন যা অন্যটির জন্য স্ট্রিংকে আলাদা মান দেয়।

সম্পাদনা: অন্যান্য ব্যক্তি যেমন উল্লেখ করেছেন। এটির refপ্রয়োজন না হলে ব্যবহার করা ভাল ধারণা নয় । ব্যবহারের refফলে পদ্ধতির অন্য কোনও কারণে যুক্তি পরিবর্তন করার স্বাধীনতা পাওয়া যায়, পদ্ধতিটির কলকারীরা এই সম্ভাবনাটি পরিচালনা করছেন তা নিশ্চিত করার জন্য কোড করা উচিত।

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

int x = 1;
Change(ref x);
Debug.Assert(x == 5);
WillNotChange(x);
Debug.Assert(x == 5); // Note: x doesn't become 10

void Change(ref int x)
{
  x = 5;
}

void WillNotChange(int x)
{
  x = 10;
}

88

আপনাকে "মান অনুসারে একটি রেফারেন্স পাস করা", এবং "একটি পরামিতি / রেফারেন্স দ্বারা যুক্তিটি পাস করার" মধ্যে পার্থক্য করতে হবে।

এই বার্তাটি গ্রুপগুলিতে প্রকাশিত হওয়ার সাথে সাথে প্রতিবার সাবধানতার সাথে লিখতে না পারার জন্য আমি এই বিষয়ে একটি যুক্তিসঙ্গত দীর্ঘ নিবন্ধ লিখেছি :)


1
ভাল নেট ভি # কোডে VB6 আপগ্রেড করার সময় আমি সমস্যার মুখোমুখি হয়েছি। এখানে ফাংশন / পদ্ধতির স্বাক্ষর রয়েছে যা রেফ, আউট এবং প্লেইন প্যারামিটার নেয়। সুতরাং আমরা কীভাবে একটি রেফের তুলনায় প্লেইন পরমের মধ্যে পার্থক্যটি আরও ভালভাবে পার্থক্য করতে পারি?
BonCodigo

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

আমি জানি না কেন ভিজ্যুয়াল স্টুডিও এখনও কী পাস হয়েছে তা স্পষ্টভাবে প্রদর্শন করে না
মনস্টার এমএমআরপিজি

3
@ মনস্টার এমএমওরপিজি: আপনি এর অর্থ কী তা আমি জানি না, আমি ভয় পাচ্ছি।
জন স্কিটি

56

.NET- এ আপনি যখন কোনও পদ্ধতিতে কোনও পরামিতি পাস করেন, একটি অনুলিপি তৈরি করা হয়। মান ধরণগুলির অর্থ হ'ল আপনি যে মানটিতে কোনও পরিবর্তন করেন তা পদ্ধতি সুযোগে হয় এবং আপনি পদ্ধতি থেকে প্রস্থান করার সময় হারিয়ে যায়।

একটি রেফারেন্স টাইপ পাস করার সময়, একটি অনুলিপিও তৈরি করা হয়, তবে এটি একটি রেফারেন্সের অনুলিপি, অর্থাৎ এখন আপনার কাছে একই বস্তুর কাছে মেমোরিতে TWO রেফারেন্স রয়েছে। সুতরাং, আপনি যদি বিষয়টিকে সংশোধন করতে রেফারেন্সটি ব্যবহার করেন তবে এটি সংশোধিত হবে। তবে আপনি যদি রেফারেন্সটি নিজেই সংশোধন করেন - আমাদের অবশ্যই এটি একটি অনুলিপি মনে রাখতে হবে - তবে পদ্ধতিটি বেরিয়ে আসার পরে কোনও পরিবর্তনও হারাতে হবে।

লোকেরা যেমন আগেই বলেছে, একটি অ্যাসাইনমেন্ট হ'ল রেফারেন্সের একটি পরিবর্তন, সুতরাং এটি হারিয়ে যায়:

public void Method1(object obj) {   
 obj = new Object(); 
}

public void Method2(object obj) {  
 obj = _privateObject; 
}

উপরের পদ্ধতিগুলি মূল বস্তুকে সংশোধন করে না।

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

 using System;

    class Program
        {
            static void Main(string[] args)
            {
                TestRef t = new TestRef();
                t.Something = "Foo";

                DoSomething(t);
                Console.WriteLine(t.Something);

            }

            static public void DoSomething(TestRef t)
            {
                t = new TestRef();
                t.Something = "Bar";
            }
        }



    public class TestRef
    {
    private string s;
        public string Something 
        { 
            get {return s;} 
            set { s = value; }
        }
    }

6
আমি এই উত্তরটি আরও ভাল পছন্দ করি তবে গ্রহণযোগ্য উত্তর। এটি রেফ কীওয়ার্ড সহ একটি রেফারেন্স টাইপ ভেরিয়েবল পাস করার পরে কী ঘটছে তা আরও পরিষ্কারভাবে ব্যাখ্যা করে explains ধন্যবাদ!
স্টিফান

17

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


16

আপনার সাথে refলিখতে পারেন:

static public void DoSomething(ref TestRef t)
{
    t = new TestRef();
}

এবং পদ্ধতিটি সম্পূর্ণ হওয়ার পরে টি পরিবর্তন করা হবে।


8

"অবজেক্ট # 24601" ফর্মটির অবজেক্ট আইডেন্টিফায়ার্ড হিসাবে fooরেফারেন্স প্রকারের (যেমন List<T>) ভেরিয়েবলগুলি (যেমন ) এর কথা ভাবেন । মনে করুন বিবৃতিটি "অবজেক্ট # 24601" (চারটি আইটেম সহ একটি তালিকা) ধরেছে causes তারপরে কলিংটি তার দৈর্ঘ্যের জন্য অবজেক্ট # 24601 জিজ্ঞাসা করবে এবং এটি 4 টি প্রতিক্রিয়া জানাবে, তাই 4 এর সমান হবে।foo = new List<int> {1,5,7,9};foofoo.Lengthfoo.Length

যদি fooব্যবহার না করে কোনও পদ্ধতিতে পাস করা হয় তবে refসেই পদ্ধতিটি অবজেক্ট # 24601 এ পরিবর্তন করতে পারে। এই জাতীয় পরিবর্তনের ফলাফল হিসাবে foo.Length4 আর সমান হতে পারে The পদ্ধতিটি নিজেই তবে পরিবর্তন করতে অক্ষম fooহবে, যা "অবজেক্ট # 24601" ধরে রাখতে থাকবে।

প্যারামিটার fooহিসাবে পাস refকরার ফলে তথাকথিত পদ্ধতিটি কেবলমাত্র # 24601 অবজেক্টে নয়, fooনিজের মধ্যেও পরিবর্তন আনতে পারে। পদ্ধতিটি একটি নতুন অবজেক্ট # 8675309 তৈরি করতে পারে এবং এতে একটি রেফারেন্স সঞ্চয় করতে পারে foo। এটি যদি তা করে থাকে fooতবে আর "অবজেক্ট # 24601" ধরে না, বরং এর পরিবর্তে "অবজেক্ট # 8675309" রাখা হবে।

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


5

এটি সি এর পয়েন্টারে একটি পয়েন্টারকে পাশ করার মতো।। নেট এটি আপনাকে ব্যক্তিগত টি বোঝায় যা পরিবর্তন করতে দেয়, ব্যক্তিগতভাবে যদিও আমি মনে করি আপনি যদি এটি করছেন তবে। নেট আপনি সম্ভবত একটি ডিজাইনের সমস্যা পেয়েছেন!


3

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


3

ref কেবল দুটি স্কোপের জন্য বিশ্বব্যাপী অঞ্চল হিসাবে নকল (বা আচরণ) করে:

  • আহ্বানকারী
  • যাকে কল করছি.

1

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


4
আপনি কোনও রেফারেন্স বা একটি মান ধরণের মানটি পাস করছেন না কেন, মান দ্বারা ডিফল্ট আচরণটি হ'ল। আপনার কেবল বুঝতে হবে যে রেফারেন্সের ধরণের সাথে আপনি যে মানটি পাশ করছেন তা একটি রেফারেন্স। এই ক্ষণস্থায়ী হিসাবে একই নয় দ্বারা রেফারেন্স।
জন স্কিটি

1

রেফারেশনটি নির্দেশ করে যে ফাংশনটি তার নিজের হাতে বা কেবলমাত্র তার মূল্য পেতে পারে।

রেফারেন্স দিয়ে পাস করা কোনও ভাষার কাছে আবদ্ধ নয়; এটি একটি প্যারামিটার বাইন্ডিং কৌশল, পাশ করে মূল্য, নাম দিয়ে পাস, প্রয়োজন অনুসারে পাস করা ...

একটি পার্শ্ববর্তী: শ্রেণীর নাম TestRefএই প্রসঙ্গে একটি লুক্কায়িত খারাপ পছন্দ;)।

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