ল্যাম্বডা এক্সপ্রেশনগুলিতে রেফ বা আউট প্যারামিটার ব্যবহার করতে পারবেন না


173

ল্যাম্বডা এক্সপ্রেশনটিতে আপনি কেন একটি রেফ বা আউট প্যারামিটার ব্যবহার করতে পারবেন না?

আমি আজ ত্রুটিটি পেরিয়ে এসে একটি কার্যকরী সন্ধান পেয়েছি তবে কেন আমি এটি একটি সংকলন-সময় ত্রুটি তা জানতে আগ্রহী ছিলাম।

CS1628 : কোনও বেনামি পদ্ধতি, ল্যাম্বডা এক্সপ্রেশন বা কোয়েরি এক্সপ্রেশনটির ভিতরে রেফার আউট বা প্যারামিটার 'প্যারামিটার' ব্যবহার করতে পারবেন না

এখানে একটি সাধারণ উদাহরণ:

private void Foo()
{
    int value;
    Bar(out value);
}

private void Bar(out int value)
{
    value = 3;
    int[] array = { 1, 2, 3, 4, 5 };
    int newValue = array.Where(a => a == value).First();
}

এটি পুনরাবৃত্তকারীদের সম্পর্কে, তবে এই পোস্টে একই যুক্তির বেশিরভাগই (এরিক লিপার্ট & mdash দ্বারাও; তিনি সর্বোপরি ভাষা নকশা দলে রয়েছেন ) ল্যাম্বডাসের ক্ষেত্রে প্রযোজ্য: < /… >
জোয়েল কোহর্ন

17
আমি কি জিজ্ঞাসা করতে পারি যে আপনি খুঁজে পেয়েছি কি workaround ছিল?
বিটলস 1692

3
আপনি কেবল একটি স্থানীয় সাধারণ পরিবর্তনশীল ঘোষণা করতে পারেন এবং এটিতে কাজ করতে পারেন, এবং ফলাফলটিকে পরে মান হিসাবে নির্ধারণ করতে পারেন ... একটি ভার্চ টেম্প্যালু = মান যোগ করুন; এবং তারপরে টেম্প্যালু দিয়ে কাজ করুন।
মাতাল কোড বানকি

উত্তর:


122

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

Func<int> Example(int p1) {
  return () => p1;
}

ক্যাপচারড ভেরিয়েবলের আর একটি সম্পত্তি হ'ল ভেরিয়েবলের পরিবর্তনগুলি ল্যাম্বডা এক্সপ্রেশনের বাইরেও দৃশ্যমান। উদাহরণস্বরূপ নিম্নলিখিত প্রিন্টগুলি 42

void Example2(int p1) {
  Action del = () => { p1 = 42; }
  del();
  Console.WriteLine(p1);
}

এই দুটি বৈশিষ্ট্য একটি নির্দিষ্ট প্রভাব তৈরি করে যা নিম্নলিখিত উপায়ে একটি রেফ প্যারামিটারের মুখে উড়ে যায়

  • রেফ প্যারামিটারগুলির একটি নির্দিষ্ট জীবনকাল থাকতে পারে। কোনও ফাংশনে রেফ প্যারামিটার হিসাবে স্থানীয় ভেরিয়েবল পাস করার কথা বিবেচনা করুন।
  • ল্যাম্বডায় পার্শ্ব প্রতিক্রিয়াগুলি রেফ প্যারামিটারে নিজেই দৃশ্যমান হওয়া দরকার। পদ্ধতির মধ্যে এবং কলারে উভয়ই।

এগুলি কিছুটা বেমানান বৈশিষ্ট্য এবং লাম্বদা এক্সপ্রেশনগুলিতে এগুলি অস্বীকৃত হওয়ার অন্যতম কারণ।


36
আমি বুঝতে পারি আমরা refল্যাম্বডা এক্সপ্রেশনটির ভিতরে ব্যবহার করতে পারি না , তবে এটি ব্যবহারের আকাঙ্ক্ষা খাওয়ানো হয়নি।
zionpi

85

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

delegate void TestDelegate (out int x);
static void Main(string[] args)
{
    TestDelegate testDel = (out int x) => { x = 10; };
    int p;
    testDel(out p);
    Console.WriteLine(p);
}

70

আপনি পারেন তবে আপনাকে অবশ্যই সমস্ত প্রকারের স্পষ্টরূপে সংজ্ঞা দিতে হবে

(a, b, c, ref d) => {...}

তবে এটি অবৈধ

(int a, int b, int c, ref int d) => {...}

বৈধ


13
এটা করে; প্রশ্ন আপনি কেন পারবেন না; উত্তর আপনি পারেন।
বেন অ্যাডামস

24
এটা না; প্রশ্ন আপনি কেন একটি বিদ্যমান ভেরিয়েবল , ইতিমধ্যে সংজ্ঞায়িত refবা outএকটি ল্যাম্বদা ভিতরে উল্লেখ করতে পারবেন না । আপনি উদাহরণ কোডটি পড়লে এটি স্পষ্ট হয় (এটি আবার পড়ার জন্য আবার চেষ্টা করুন)। গৃহীত উত্তরগুলি পরিষ্কারভাবে ব্যাখ্যা করে কেন। আপনার উত্তরটি ল্যাম্বডা ব্যবহার refবা out পরামিতি সম্পর্কে ।
সামগ্রিকভাবে

4
@ edc65 ঠিক আছে ... প্রশ্নটির বিষয়টির সাথে এর কোনও যোগসূত্র নেই, যা লাম্বা অভিব্যক্তির বিষয়বস্তু সম্পর্কে (ডানদিকে) নয়, এর প্যারামিটার তালিকাটি (বাম দিকে) নয়। এটি বিচিত্র যে এটি 26 টি উপায়ে পেয়েছে।
জিম বাল্টার

6
এটি যদিও আমাকে সাহায্য করেছিল। তার জন্য +1। ধন্যবাদ
এমাদ

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

5

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

সিনট্যাক্স প্রদর্শনের জন্য, অনুসন্ধান করার সময় আমি যা করার চেষ্টা করছিলাম:

public static ScanOperation<TToken> CreateScanOperation(
    PrattTokenDefinition<TNode, TToken, TParser, TSelf> tokenDefinition)
{
    var oldScanOperation = tokenDefinition.ScanOperation; // Closures still work.
    return delegate(string text, ref int position, ref PositionInformation currentPosition)
        {
            var token = oldScanOperation(text, ref position, ref currentPosition);
            if (token == null)
                return null;
            if (tokenDefinition.LeftDenotation != null)
                token._led = tokenDefinition.LeftDenotation(token);
            if (tokenDefinition.NullDenotation != null)
                token._nud = tokenDefinition.NullDenotation(token);
            token.Identifier = tokenDefinition.Identifier;
            token.LeftBindingPower = tokenDefinition.LeftBindingPower;
            token.OnInitialize();
            return token;
        };
}

কেবল মনে রাখবেন যে ল্যাম্বডাস প্রক্রিয়াগতভাবে এবং গাণিতিকভাবে সুরক্ষিত (কারণ পূর্বে উল্লিখিত রেফের মান প্রচারের কারণে): আপনি কৃমিতে একটি ক্যান খুলতে পারেন। এই সিনট্যাক্সটি ব্যবহার করার সময় সাবধানতার সাথে চিন্তা করুন।


3
আমি মনে করি আপনি প্রশ্নটি ভুল বুঝেছেন। প্রশ্নটি ছিল যে ল্যাম্বদা কেন তার ধারক পদ্ধতিতে রেফ / আউট ভেরিয়েবল অ্যাক্সেস করতে পারে না, কেন ল্যাম্বদা নিজেই রেফ / আউট ভেরিয়েবলগুলি রাখতে পারে না। আফ্রিকের পরবর্তীকালের কোনও ভাল কারণ নেই। আজ আমি একটি ল্যাম্বদা লিখেছি (a, b, c, ref d) => {...}এবং refত্রুটি বার্তাটি "প্যারামিটার '4' অবশ্যই 'রেফ' কীওয়ার্ডের সাথে ঘোষণা করতে হবে তা দিয়ে লালরেখার হয়ে গেছে। Facepalm! পিএস "রেফ মান মূল্য প্রচার" কি?
কিওয়ার্টি

1
@ কিওয়ার্টি আমি পূর্ণ পরামিতি দিয়ে কাজ করতে পেরেছি, এর অর্থ, এ, বি, সি এবং ডি এর ধরণগুলি অন্তর্ভুক্ত করে এবং এটি কাজ করে। বেনএডামসের উত্তর দেখুন (যদিও তিনি মূল প্রশ্নটিও ভুল বোঝেন)।
এড বেয়িয়েটস

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

আসলে জিজ্ঞাসা করা প্রশ্নের সাথে এর কোনও সম্পর্ক নেই ... বেন অ্যাডামসের উত্তর অনুসারে গৃহীত উত্তর এবং মন্তব্যগুলি দেখুন, যিনি একইভাবে প্রশ্নটিকে ভুল বুঝেছিলেন।
জিম বাল্টার

1

এবং সম্ভবত এই?

private void Foo()
{
    int value;
    Bar(out value);
}

private void Bar(out int value)
{
    value = 3;
    int[] array = { 1, 2, 3, 4, 5 };
    var val = value; 
    int newValue = array.Where(a => a == val).First();
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.