কেন সি # রেফারেন্সগুলি ফেরত সমর্থন করে না?


141

আমি পড়েছি যে .NET রেফারেন্সগুলির ফিরতি সমর্থন করে, কিন্তু সি # দেয় না। কোন বিশেষ কারণ আছে? আমি কেন এমন কিছু করতে পারি না:

static ref int Max(ref int x, ref int y) 
{ 
  if (x > y) 
    return ref x; 
  else 
    return ref y; 
} 

8
উম ... অনুগ্রহ করে দয়া করে?
RPM1984

5
সি # এর মান এবং রেফারেন্সের ধরণ রয়েছে এবং আপনার অর্থ কী তা উভয়ই ফিরিয়ে দেওয়া যেতে পারে।
পুনরায় চালু করুন

আমি এরকম কিছু সম্পর্কে কথা বলছিreturn ref x
টম সারদুয়

2
4 বছর পরে, আপনি C# 7:) এর সাথে ঠিক এটি করতে পারেন :)
আরঘ্যা সি

উত্তর:


188

এই প্রশ্নটি 23 ই জুন 2011 এ আমার ব্লগের বিষয় ছিল । মহান প্রশ্নের জন্য ধন্যবাদ!

সি # টিম এটি সি # 7-র জন্য বিবেচনা করছে details বিশদের জন্য https://github.com/dotnet/roslyn/issues/5233 দেখুন ।

আপডেট: বৈশিষ্ট্যটি এটি সি # 7 এ তৈরি করেছে!


আপনি সঠিক; .NET এমন পদ্ধতিগুলি সমর্থন করে যা ভেরিয়েবলগুলিতে পরিচালিত রেফারেন্সগুলি ফিরিয়ে দেয় । .NET স্থানীয় ভেরিয়েবলগুলিকে সমর্থন করে যা অন্যান্য ভেরিয়েবলের পরিচালিত রেফারেন্স ধারণ করে। (তবে লক্ষ করুন যে .NET ক্ষেত্র বা অ্যারেগুলিকে সমর্থন করে না যা অন্যান্য ভেরিয়েবলের পরিচালিত রেফারেন্স ধারণ করে কারণ এটি অতিরিক্তভাবে আবর্জনা সংগ্রহের গল্পকে জটিল করে তোলে Also এছাড়াও "ভেরিয়েবলের জন্য পরিচালিত রেফারেন্স" প্রবন্ধটি বস্তুতে রূপান্তরিত নয় , এবং তাই এটি ব্যবহার করা যেতে পারে না জেনেরিক প্রকার বা পদ্ধতিতে যুক্তিগুলি টাইপ করুন))

মন্তব্যকারী "আরপিএম 1984" কোনও কারণে এই সত্যটির জন্য প্রশংসা চেয়েছিল। RPM1984 আমি আপনাকে নেট .NET এর বৈশিষ্ট্য সম্পর্কে তথ্যের জন্য CLI স্পেসিফিকেশন পার্টিশন I ধারা 8.2.1.1, "পরিচালিত পয়েন্টার এবং সম্পর্কিত প্রকারগুলি" পড়তে উত্সাহিত করি।

সি # এর একটি সংস্করণ তৈরি করা সম্পূর্ণভাবে সম্ভব যা এই দুটি বৈশিষ্ট্যই সমর্থন করে। আপনি তখন মত জিনিস করতে পারে

static ref int Max(ref int x, ref int y) 
{ 
  if (x > y) 
    return ref x; 
  else 
    return ref y; 
} 

এবং তারপরে এটি কল করুন

int a = 123;
int b = 456; 
ref int c = ref Max(ref a, ref b); 
c += 100;
Console.WriteLine(b); // 556!

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

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

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

ref int M1(ref int x)
{
    return ref x;
}

ref int M2()
{
    int y = 123;
    return ref M1(ref y); // Trouble!
}

int M3()
{
    ref int z = ref M2();
    return z;
}

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

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

(সম্পর্কিত প্রশ্নগুলিও দেখুন কি সি # তে চলকটির কোনও রেফারেন্স ফেরানো সম্ভব? এবং আমি কি সি ++ এর মতো সি # ফাংশনের অভ্যন্তরে কোনও রেফারেন্স ব্যবহার করতে পারি? )


4
@ এরিকলিপার্ট: আমার কোন দৃ example়প্রত্যয়ী উদাহরণ নেই যা আমি ভাবছিলাম। দুর্দান্ত এবং আকর্ষণীয় প্রতিক্রিয়া
টম সার্ডু

1
@ এরিক: আপনার উদাহরণে, ফিরে আসার পরে y বেঁচে থাকার পক্ষে আরও কি উপযুক্ত হবে না M2? আমি আশা করব যে এই বৈশিষ্ট্যটি ল্যাম্বডাস স্থানীয়দের ক্যাপচারের মতো কাজ করবে। অথবা আপনি প্রস্তাবিত আচরণটি কারণ সিএলআর সেই দৃশ্যটি পরিচালনা করে কীভাবে?
ফেডার

3
@ এরিক: আইএমএইচও মান বৈশিষ্ট্যগুলির সাথে সম্পর্কিত বৈশিষ্ট্যগুলি ফেরত উল্লেখ করার ক্ষমতা। নেট ভাষাগুলিতে একটি বড় বাদ পড়ে। অ্যার যদি কোনও মান ধরণের (যেমন পয়েন্ট) অ্যারে হয়, তবে কেউ বলতে পারে যেমন অর (3) .X = 9 এবং জেনে নিতে পারেন যে আরার (9) .X বা এমনকি সামোথেরআরে (2) এর মান পরিবর্তন হয়নি। এক্স; যদি এরর পরিবর্তে কিছু রেফারেন্স ধরণের অ্যারে হত তবে এরকম কোনও গ্যারান্টি উপস্থিত থাকবে না। কোন অ্যারের সূচক অপারেটর একটি রেফারেন্স দেয় তা সত্য যে দরকারী; আমি অত্যন্ত দুর্ভাগ্যজনক হিসাবে বিবেচনা করি যে অন্য কোনও ধরণের সংগ্রহই এই জাতীয় কার্যকারিতা সরবরাহ করতে পারে না।
সুপারক্যাট

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

1
@ থান্ডারগ্রি: এটি "অনিরাপদ" এর জন্য সি # দর্শন - যদি আপনি সম্ভবত মেমোরি-অনিরাপদ এমন কোড লিখে থাকেন তবে সি # জোর দিয়ে বলেছেন যে আপনি এটিকে "অনিরাপদ" হিসাবে চিহ্নিত করেছেন, যাতে আপনি স্মৃতি সুরক্ষার জন্য দায়িত্ব নিচ্ছেন। সি # এর বৈশিষ্ট্যটির ইতিমধ্যে অনিরাপদ সংস্করণ রয়েছে, তবে শর্তাবলীর ভেরিয়েবলটি পরিচালনা না করা টাইপের provided প্রশ্নটি হ'ল সি # টিমের এমন কোনও অনিরাপদ সংস্করণ করা উচিত যা পরিচালিত ধরণের পরিচালনা করে। যদি এটি করা বিকাশকারীদের পক্ষে ভয়ঙ্কর বাগগুলি লিখতে সহজ করে তোলে তবে তা ঘটবে না। সি # হ'ল সি ++ নয়, এমন একটি ভাষা যা ভয়ঙ্কর বাগগুলি লিখতে সহজ করে। সি # ডিজাইন দ্বারা নিরাপদ।
এরিক লিপার্ট

21

আপনি এমন পদ্ধতির কথা বলছেন যা কোনও মান ধরণের রেফারেন্স দেয়। সি # তে একমাত্র বিল্ট-ইন উদাহরণ যা আমি জানি একটি মান ধরণের অ্যারে-অ্যাক্সেসর:

public struct Point
{
    public int X { get; set; }
    public int Y { get; set; }
}

এবং এখন সেই স্ট্রাক্টের একটি অ্যারে তৈরি করুন:

var points = new Point[10];
points[0].X = 1;
points[0].Y = 2;

এই ক্ষেত্রে points[0], এরে indexer , struct একটি রেফারেন্স ফিরে আসছে। আপনার নিজস্ব সূচক (উদাহরণস্বরূপ একটি কাস্টম সংগ্রহের জন্য) লেখা অসম্ভব , এতে একই "রেফারেন্স ফেরান" আচরণ রয়েছে।

আমি সি # ভাষাটি ডিজাইন করিনি যাতে এটি সমর্থন না করার পিছনে সমস্ত যুক্তি আমি জানি না তবে আমি মনে করি যে সংক্ষিপ্ত উত্তরটি হতে পারে: আমরা এটিকে ছাড়া ঠিক জরিমানা পেতে পারি।


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

1

আপনি সর্বদা এমন কিছু করতে পারেন:

public delegate void MyByRefConsumer<T>(ref T val);

public void DoSomethingWithValueType(MyByRefConsumer<int> c)
{
        int x = 2;
        c(ref x);
        //Handle potentially changed x...
}

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