কোনও সম্পত্তি স্বাক্ষরে সি # তে => অ্যাসাইনমেন্টটি কী


229

আমি কিছু কোড জুড়ে এসেছিল যা বলেছিল

public int MaxHealth => 
         Memory[Address].IsValid ? 
         Memory[Address].Read<int>(Offs.Life.MaxHp) : 
         0;

এখন আমি লাম্বদা মত প্রকাশের সাথে কিছুটা পরিচিত। আমি এটি এটি এইভাবে ব্যবহার করতে দেখিনি।

উপরোক্ত বিবৃতি এবং এর মধ্যে পার্থক্য কী হবে

public int MaxHealth  = x ? y:z;

4
প্রথম ব্লকটি সম্পত্তি দ্বিতীয়টি পরিবর্তনশীল
এমকাজেম আখগারি

14
@ এমকাজেমআখগারি * একটি ক্ষেত্র, পরিবর্তনশীল নয়।
মাফাই

উত্তর:


376

আপনি যা দেখছেন তা হ'ল ল্যাম্বডা এক্সপ্রেশন নয় এমন একটি অভিব্যক্তি-দেহী সদস্য

সংকলকটি যখন একটি অভিব্যক্ত-দেহযুক্ত সম্পত্তি সদস্যের মুখোমুখি হয় , এটি মূলত এটিকে এ জাতীয় উপস্থায় রূপান্তর করে:

public int MaxHealth
{
    get
    {
        return Memory[Address].IsValid ? Memory[Address].Read<int>(Offs.Life.MaxHp) : 0;
    }
}

( ট্রাইরোসলিন নামে একটি সরঞ্জামে কোডটি পাম্প করে আপনি এটি নিজের জন্য যাচাই করতে পারেন ))

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

আপনি দেখতে পাচ্ছেন, এক্সপ্রেশন-দেহী সদস্যদের হাতে গোটা শর্টকাট রয়েছে যা সম্পত্তি সদস্যদের আরও কমপ্যাক্ট করে তোলে:

  • returnবিবৃতি ব্যবহার করার দরকার নেই কারণ সংকলকটি অনুমান করতে পারে যে আপনি প্রকাশের ফলাফলটি ফিরিয়ে দিতে চান
  • স্টেটমেন্ট ব্লক তৈরি করার দরকার নেই কারণ শরীরটি কেবল একটিই অভিব্যক্তি
  • getকীওয়ার্ডটি ব্যবহার করার দরকার নেই কারণ এটি এক্সপ্রেশন-দেহযুক্ত সদস্য সিনট্যাক্স ব্যবহারের দ্বারা নিহিত।

আমি চূড়ান্ত বিষয়টিকে সাহসী করে তুলেছি কারণ এটি আপনার আসল প্রশ্নের সাথে প্রাসঙ্গিক, যার উত্তর আমি এখনই দেব।

মধ্যে পার্থক্য...

// expression-bodied member property
public int MaxHealth => x ? y:z;

এবং...

// field with field initializer
public int MaxHealth = x ? y:z;

পার্থক্য হিসাবে একই ...

public int MaxHealth
{
    get
    {
        return x ? y:z;
    }
}

এবং...

public int MaxHealth = x ? y:z;

কোন - যদি আপনি বৈশিষ্ট্যগুলি বুঝতে পারেন - তবে তা স্পষ্ট হওয়া উচিত।

তবে কেবল স্পষ্ট করেই বলা যায়: প্রথম তালিকাটি হুডের নীচে একজন গিটার সহ এমন একটি সম্পত্তি যা প্রতিবার আপনি এটি অ্যাক্সেস করার সময় বলা হবে called দ্বিতীয় তালিকাটি হল ক্ষেত্র আরম্ভকারক সহ এমন একটি ক্ষেত্র, যার প্রকারটি ইনস্ট্যান্ট করা হলে তার অভিব্যক্তিটি কেবল একবার মূল্যায়ন করা হয়।

বাক্যবিন্যাসের এই পার্থক্যটি আসলে বেশ সূক্ষ্ম এবং একটি "গোটচা" হতে পারে যা বিল ওয়াগনার "এসি # 6 গোছা: ইনিশিয়েশন বনাম এক্সপ্রেশন বডিড মেম্বারস" শিরোনামে একটি পোস্টে বর্ণনা করেছেন

যদিও প্রকাশ-সাকার সদস্য ল্যামডা expression- মত , তারা না ল্যামডা এক্সপ্রেশন। মৌলিক পার্থক্যটি হ'ল ল্যাম্বডা এক্সপ্রেশনটির ফলে ডেলিগেটের উদাহরণ বা এক্সপ্রেশন ট্রি হয়। এক্সপ্রেশন-শারীরিক সদস্যগণ পর্দার পিছনে একটি সম্পত্তি উত্পন্ন করার জন্য সংকলকটির কেবল নির্দেশ are মিল (কমবেশি) শুরু হয় এবং তীর ( =>) দিয়ে শেষ হয় with

আমি আরও যোগ করব যে এক্সপ্রেশন-দেহযুক্ত সদস্যরা সম্পত্তি সদস্যদের মধ্যে সীমাবদ্ধ নয়। তারা এই সমস্ত সদস্যের উপর কাজ করে:

  • প্রোপার্টি
  • Indexers
  • পদ্ধতি
  • অপারেটর

মধ্যে যোগ করা হয়েছে সি # 7.0

তবে তারা এই সদস্যদের নিয়ে কাজ করে না:

  • নেস্টেড প্রকার
  • ঘটনাবলী
  • ক্ষেত্রসমূহ

6
সি # 7 হিসাবে, কনস্ট্রাক্টর এবং ফাইনালাইজারগুলিও সমর্থিত। ডকস.মাইক্রোসফট.এইন
ডটনেট /

8
@ বিজিয়ার আমাদের ফাংশনাল প্রোগ্রামার বানানোর ষড়যন্ত্র। যদি চিরদিনের মতো হয় !!
সেন্টিনেল

সুপার দুর্দান্ত উত্তর!
জাইমে আরোইও গার্সিয়া

2
বিল ওয়াগনারের পোস্টের লিঙ্কটি বর্তমানে ভেঙে গেছে। আমি নতুন URL পাওয়া গেছে: codeproject.com/Articles/1064964/...
ভেজে সিম্পসন

36

ঠিক আছে ... আমি একটি মন্তব্য করেছি যে তারা আলাদা ছিল তবে ঠিক কীভাবে তবে এখন আমি জানি তা ব্যাখ্যা করতে পারিনি।

String Property { get; } = "value";

যেমন হয় না

String Property => "value";

পার্থক্য এখানে ...

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

আমার পরিস্থিতিতে আমি আমার সম্পত্তিটি একটি ভিউর জন্য ভিডমোডেলে একটি কমান্ড শুরু করে দিয়েছিলাম। আমি এক্সপ্রেশন বডিড ইনিশিয়ালাইজার ব্যবহার করার জন্য সম্পত্তিটি পরিবর্তন করেছি এবং CanExecute কমান্ডটি কাজ করা বন্ধ করে দিয়েছে।

এটি দেখতে কেমন দেখাচ্ছে এবং এখানে যা ঘটছিল তা এখানে।

Command MyCommand { get; } = new Command();  //works

আমি এখানে এটি পরিবর্তন করেছি।

Command MyCommand => new Command();  //doesn't work properly

এখানে পার্থক্যটি যখন আমি ব্যবহার { get; } =করি তখন আমি সেই সম্পত্তিটিতে স্যাম কমান্ড তৈরি ও রেফারেন্স করি। আমি যখন ব্যবহার =>করি তখন আমি একটি নতুন কমান্ড তৈরি করি এবং প্রতিবার সম্পত্তি বলার পরে তা ফিরিয়ে আনি। অতএব, আমি কখনই CanExecuteআমার কমান্ডের আপডেটটি আপডেট করতে পারিনি কারণ আমি সর্বদা এটি আদেশের নতুন রেফারেন্সটি আপডেট করার জন্য বলছিলাম।

{ get; } = // same reference
=>         // new reference

যা যা বলেছিল, আপনি যদি কেবল কোনও ব্যাকিং ফিল্ডের দিকে ইশারা করেন তবে তা ঠিক কাজ করে। এটি কেবল তখনই ঘটে যখন অটো বা এক্সপ্রেশন বডি ফেরতের মান তৈরি করে।


8
=> বাক্য গঠনটি নতুন কমান্ড () ফেরত পাওয়ার সমতুল্য; } বাক্য গঠন.
মাফেই

35

এটি সি # 6 এর একটি নতুন বৈশিষ্ট্য যা একটি এক্সপ্রেশন বডিড মেম্বার নামে পরিচিত যা আপনাকে ল্যাম্বডা ফাংশনের মতো কেবলমাত্র একজন গেটর সম্পত্তি সংজ্ঞায়িত করতে দেয়।

এটি নিম্নলিখিতগুলির জন্য সিনট্যাকটিক চিনি হিসাবে বিবেচিত হলেও তারা অভিন্ন আইএল উত্পাদন করতে পারে না :

public int MaxHealth
{
    get
    {
        return Memory[Address].IsValid
               ?   Memory[Address].Read<int>(Offs.Life.MaxHp)
               :   0;
    }
}

দেখা যাচ্ছে যে আপনি যদি উপরের দুটি সংস্করণ সংকলন করেন এবং প্রতিটিটির জন্য উত্পন্ন আইএলটির তুলনা করেন তবে আপনি দেখতে পাবেন যে সেগুলি নিকটেই রয়েছে একই।

এই উত্তরের ক্লাসিক সংস্করণের জন্য আইএল এখানে দেওয়া ক্লাসে যখন সংজ্ঞায়িত করা হয় TestClass:

.property instance int32 MaxHealth()
{
    .get instance int32 TestClass::get_MaxHealth()
}

.method public hidebysig specialname 
    instance int32 get_MaxHealth () cil managed 
{
    // Method begins at RVA 0x2458
    // Code size 71 (0x47)
    .maxstack 2
    .locals init (
        [0] int32
    )

    IL_0000: nop
    IL_0001: ldarg.0
    IL_0002: ldfld class [mscorlib]System.Collections.Generic.Dictionary`2<int64, class MemoryAddress> TestClass::Memory
    IL_0007: ldarg.0
    IL_0008: ldfld int64 TestClass::Address
    IL_000d: callvirt instance !1 class [mscorlib]System.Collections.Generic.Dictionary`2<int64, class MemoryAddress>::get_Item(!0)
    IL_0012: ldfld bool MemoryAddress::IsValid
    IL_0017: brtrue.s IL_001c

    IL_0019: ldc.i4.0
    IL_001a: br.s IL_0042

    IL_001c: ldarg.0
    IL_001d: ldfld class [mscorlib]System.Collections.Generic.Dictionary`2<int64, class MemoryAddress> TestClass::Memory
    IL_0022: ldarg.0
    IL_0023: ldfld int64 TestClass::Address
    IL_0028: callvirt instance !1 class [mscorlib]System.Collections.Generic.Dictionary`2<int64, class MemoryAddress>::get_Item(!0)
    IL_002d: ldarg.0
    IL_002e: ldfld class Offs TestClass::Offs
    IL_0033: ldfld class Life Offs::Life
    IL_0038: ldfld int64 Life::MaxHp
    IL_003d: callvirt instance !!0 MemoryAddress::Read<int32>(int64)

    IL_0042: stloc.0
    IL_0043: br.s IL_0045

    IL_0045: ldloc.0
    IL_0046: ret
} // end of method TestClass::get_MaxHealth

এবং এখানে নামের ক্লাসে সংজ্ঞায়িত হওয়ার সময় এক্সপ্রেশনটি দেহযুক্ত সদস্য সংস্করণের জন্য আইএল রয়েছে TestClass:

.property instance int32 MaxHealth()
{
    .get instance int32 TestClass::get_MaxHealth()
}

.method public hidebysig specialname 
    instance int32 get_MaxHealth () cil managed 
{
    // Method begins at RVA 0x2458
    // Code size 66 (0x42)
    .maxstack 2

    IL_0000: ldarg.0
    IL_0001: ldfld class [mscorlib]System.Collections.Generic.Dictionary`2<int64, class MemoryAddress> TestClass::Memory
    IL_0006: ldarg.0
    IL_0007: ldfld int64 TestClass::Address
    IL_000c: callvirt instance !1 class [mscorlib]System.Collections.Generic.Dictionary`2<int64, class MemoryAddress>::get_Item(!0)
    IL_0011: ldfld bool MemoryAddress::IsValid
    IL_0016: brtrue.s IL_001b

    IL_0018: ldc.i4.0
    IL_0019: br.s IL_0041

    IL_001b: ldarg.0
    IL_001c: ldfld class [mscorlib]System.Collections.Generic.Dictionary`2<int64, class MemoryAddress> TestClass::Memory
    IL_0021: ldarg.0
    IL_0022: ldfld int64 TestClass::Address
    IL_0027: callvirt instance !1 class [mscorlib]System.Collections.Generic.Dictionary`2<int64, class MemoryAddress>::get_Item(!0)
    IL_002c: ldarg.0
    IL_002d: ldfld class Offs TestClass::Offs
    IL_0032: ldfld class Life Offs::Life
    IL_0037: ldfld int64 Life::MaxHp
    IL_003c: callvirt instance !!0 MemoryAddress::Read<int32>(int64)

    IL_0041: ret
} // end of method TestClass::get_MaxHealth

C # 6 এ এবং অন্যান্য নতুন বৈশিষ্ট্যগুলি সম্পর্কে আরও তথ্যের জন্য https://msdn.microsoft.com/en-us/magazine/dn802602.aspx দেখুন ।

সি # তে একটি ক্ষেত্র এবং সম্পত্তি প্রাপ্তির মধ্যে পার্থক্য সম্পর্কে এই পোস্টটি সি # 3.0+সম্পত্তি এবং ক্ষেত্রের মধ্যে পার্থক্যটি দেখুন ।

হালনাগাদ:

নোট করুন যে অভিব্যক্তি-দেহী সদস্যদের সি # 7.0-এ সম্পত্তি, নির্মাতা, চূড়ান্তকরণকারী এবং সূচক অন্তর্ভুক্ত করার জন্য প্রসারিত করা হয়েছিল।


16

একে এক্সপ্রেশন বডিয়েড মেম্বার বলা হয় এবং এটি সি # 6 এ প্রবর্তিত হয়েছিল এটি getএকটিমাত্র সম্পত্তির উপরে নিছক সিনট্যাকটিক চিনি ।

এটি সমান:

public int MaxHealth { get { return Memory[Address].IsValid ?
                             Memory[Address].Read<int>(Offs.Life.MaxHp) : 0; }

একটি পদ্ধতির ঘোষণার সমতুল্য উপলব্ধ:

public string HelloWorld() => "Hello World";

প্রধানত আপনাকে বয়লারপ্লেট সংক্ষিপ্তকরণের অনুমতি দিচ্ছে।


7

আপনি সি # 6 ব্যবহার করছেন তবে অন্য একটি উল্লেখযোগ্য বিষয়:

'=>' পরিবর্তে 'get' এর ব্যবহার করা যাবে এবং শুধুমাত্র 'শুধুমাত্র get' পদ্ধতি জন্য - এটা একটি 'সেট' এর সাথে ব্যবহার করা যাবে না।

সি # 7 এর জন্য, নীচে @ বেইজেনমোরের মন্তব্য দেখুন - এটি এখন আরও জায়গায় ব্যবহার করা যেতে পারে। এখানে একটি ভাল রেফারেন্স - https://csharp.christiannagel.com/2017/01/25/expressionbodiedmembers/


8
আপনি যদি সি # 7 ব্যবহার করছেন তবে আর সত্য নয় "" সি # 7.0 উত্পাদনশীলতা বর্ধনের সাথে অব্যাহত থাকে Exp এক্সপ্রেশন-দেহী সদস্যরা পদ্ধতি # এবং বৈশিষ্ট্যগুলির জন্য সি # 6 দিয়ে উপলব্ধ রয়েছে, এখন তারা নির্মাণকারী, ধ্বংসকারী, সম্পত্তি অ্যাক্সেসর এবং ইভেন্ট অ্যাকসেসরগুলির সাথে ব্যবহার করা যেতে পারে যেমন." ( উত্স )
অ্যাভেনমোর

1

নিম্নোক্ত বিবৃতি দ্বারা ভাগ করা জন্য অ্যালেক্স বুকার মধ্যে তাদের উত্তর

সংকলকটি যখন একটি অভিব্যক্ত-দেহযুক্ত সম্পত্তি সদস্যের মুখোমুখি হয়, এটি মূলত এটিকে এ জাতীয় উপস্থায় রূপান্তর করে:

দয়া করে নীচের স্ক্রিনশটটি দেখুন , এটি দেখায় যে কীভাবে এই বিবৃতিটি ( শার্পল্যাব লিঙ্কটি ব্যবহার করে )

public string APIBasePath => Configuration.ToolsAPIBasePath;

রূপান্তর

public string APIBasePath
{
    get
    {
        return Configuration.ToolsAPIBasePath;
    }
}

স্ক্রীনশট: এখানে চিত্র বর্ণনা লিখুন

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