c# - যখন কাঠামো ব্যবহার করবেন?




struct (19)

কখন আপনি C # এ ক্লাস এবং struct ব্যবহার করবেন? আমার ধারণাগত মডেলটি যখন বস্তুগুলি কেবল মূল্যের একটি সংগ্রহের সময় হয় তখন structs ব্যবহার করা হয়। যৌক্তিকভাবে একসঙ্গে একটি সংহতিপূর্ণ সব তাদের একসঙ্গে রাখা একটি উপায়।

আমি here এই নিয়ম জুড়ে here :

  • একটি কাঠামো একটি একক মান প্রতিনিধিত্ব করা উচিত।
  • একটি struct 16 মেগাবাইট কম একটি মেমরি পদচিহ্ন থাকা উচিত।
  • একটি গঠন সৃষ্টি পরে পরিবর্তন করা উচিত নয়।

এই নিয়ম কাজ করে? একটি struct semantically অর্থ কি?


"এটি একটি মান" উত্তর ছাড়াও, structs ব্যবহার করার জন্য একটি নির্দিষ্ট দৃশ্যকল্প যখন আপনি জানেন যে আপনার কাছে এমন একটি ডেটা রয়েছে যা আবর্জনা সংগ্রহের সমস্যাগুলি সৃষ্টি করে এবং আপনার প্রচুর বস্তু থাকে। উদাহরণস্বরূপ, একটি বড় তালিকা / ব্যক্তির দৃষ্টান্ত অ্যারে। প্রাকৃতিক রূপক এখানে একটি শ্রেণী, তবে যদি আপনার দীর্ঘস্থায়ী ব্যক্তি দীর্ঘস্থায়ী ব্যক্তি সংখ্যা থাকে, তবে তারা জেন -২ টি বন্ধ করে এবং জিসি স্টলগুলি ঘটাতে পারে। যদি দৃশ্যকল্পটি এটির জন্য বৈধ হয়, তবে এখানে একটি সম্ভাব্য পন্থা হল ব্যক্তি structs , অর্থাৎ Person[] একটি অ্যারের (তালিকা নয়) ব্যবহার করা। এখন, GEN-2 তে লক্ষ লক্ষ বস্তু থাকার পরিবর্তে, আপনার LOH- এ একটি একক অংশ রয়েছে (আমি এখানে কোন স্ট্রিংগুলি অনুভব করছি না - অর্থাত কোনও রেফারেন্স ছাড়াই বিশুদ্ধ মান)। এই খুব সামান্য জিসি প্রভাব আছে।

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

int index = ...
int id = peopleArray[index].Id;

মনে রাখবেন যে মূল্যগুলি অপরিবর্তনীয় রাখা এখানে সাহায্য করবে। আরো জটিল যুক্তি জন্য, একটি বাই-রেফার প্যারামিটারের সাথে একটি পদ্ধতি ব্যবহার করুন:

void Foo(ref Person person) {...}
...
Foo(ref peopleArray[index]);

আবার, এই জায়গায় - আমরা মূল্য অনুলিপি না।

খুব নির্দিষ্ট পরিস্থিতিতে, এই কৌশল খুব সফল হতে পারে; যাইহোক, এটি একটি মোটামুটি উন্নত স্কেনারিও যা শুধুমাত্র আপনি যদি কী করছেন এবং কেন তা জানতে চেষ্টা করেন। ডিফল্ট এখানে একটি বর্গ হতে হবে।


.NET value types এবং reference types সমর্থন করে (জাভাতে, আপনি কেবল রেফারেন্স ধরনগুলি সংজ্ঞায়িত করতে পারেন)। reference types উদাহরণ ব্যবস্থাপনা পরিচালিত হিপে বরাদ্দ করা হয় এবং তাদের কাছে কোন উল্লেখযোগ্য রেফারেন্স না থাকলেও আবর্জনা সংগ্রহ করা হয়। অন্যদিকে value types উদাহরণগুলি stack মধ্যে বরাদ্দ করা হয় এবং এভাবে বরাদ্দকৃত স্মৃতি পুনরুদ্ধার করা হয় যত তাড়াতাড়ি তাদের সুযোগ শেষ হয়। এবং অবশ্যই, value types মান দ্বারা পাস করা হয়, এবং reference types দ্বারা রেফারেন্স reference types । সিস্টেম সি স্ট্রিং ব্যতীত সমস্ত সি # আদিম ডাটা টাইপ, মান ধরনের।

ক্লাস উপর গঠন ব্যবহার করার সময়,

সি #, structs value types , ক্লাস reference types । আপনি enum কীওয়ার্ড এবং struct কীওয়ার্ড ব্যবহার করে, C # এ মান টাইপ তৈরি করতে পারেন। একটি reference type value type পরিবর্তে একটি value type ব্যবহার করে পরিচালিত হিপের কম বস্তুগুলি হ্রাস পাবে, যার ফলে গার্বেজ সংগ্রাহক (জিসি) কম ঘন ঘন জিসি চক্রগুলির উপর কম লোড এবং ফলস্বরূপ আরও ভালো কর্মক্ষমতা হবে। যাইহোক, value types তাদের downsides খুব আছে। একটি বড় কাঠামোর কাছাকাছি পাস একটি রেফারেন্স পাস চেয়ে স্পষ্টভাবে ব্যয়বহুল, যে একটি সুস্পষ্ট সমস্যা। অন্য সমস্যা boxing/unboxing সঙ্গে যুক্ত ওভারহেড হয়। যদি আপনি boxing/unboxing মানে কী ভাবছেন, boxing এবং unboxing সম্পর্কে একটি ভাল ব্যাখ্যা করার জন্য এই লিঙ্কগুলি অনুসরণ করুন। পারফরম্যান্সের পাশাপাশি, এমন সময় আছে যখন আপনার কাছে কেবল মুল্যার্থের শব্দগুলি থাকা দরকার, যা reference types আপনার কাছে থাকা থাকলে খুব কঠিন (বা কুৎসিত) প্রয়োগ করতে হবে। আপনি শুধুমাত্র value types ব্যবহার করা উচিত, যখন আপনি অনুলিপি semantics প্রয়োজন বা স্বয়ংক্রিয়ভাবে এই ধরনের arrays মধ্যে স্বয়ংক্রিয় প্রাথমিককরণ প্রয়োজন।


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

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


আমি মূল পোস্টে দেওয়া নিয়ম সঙ্গে একমত না। এখানে আমার নিয়ম:

1) আপনি অ্যারে মধ্যে সংরক্ষিত যখন কর্মক্ষমতা জন্য structs ব্যবহার করুন। (দেখুন যখন structs উত্তর আছে? )

2) আপনার সি / সি ++ থেকে / কোড থেকে কাঠামোগত ডেটা পাস করার জন্য তাদের দরকার

3) আপনি প্রয়োজন না হওয়া পর্যন্ত structs ব্যবহার করবেন না:

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

ওপের উৎসটি কিছুটা বিশ্বাসযোগ্যতা আছে ... কিন্তু মাইক্রোসফট সম্পর্কে কী - স্ট্রাক্স ব্যবহারের অবস্থান কী? আমি মাইক্রোসফ্ট থেকে কিছু অতিরিক্ত লার্নিং চাওয়া, এবং এখানে কি পাওয়া যায়:

টাইপের পরিবর্তে ছোট এবং সাধারণভাবে স্বল্পকালীন বা অন্যান্য বস্তুর মধ্যে সাধারণত এমবেড করা থাকলে ক্লাসের পরিবর্তে একটি কাঠামো সংজ্ঞায়িত করার কথা বিবেচনা করুন।

টাইপটি যদি নিম্নোক্ত বৈশিষ্ট্যগুলির মধ্যে থাকে তবে গঠনটি সংজ্ঞায়িত করবেন না:

  1. এটি যৌক্তিকভাবে একটি একক মান উপস্থাপিত করে, যা আদিম প্রকারের (পূর্ণসংখ্যা, দ্বিগুণ, ইত্যাদি) অনুরূপ।
  2. এটি 16 বাইট চেয়ে ছোট একটি উদাহরণ আকার আছে।
  3. এটা অপরিবর্তনীয়।
  4. এটা ঘন ঘন বক্স করা হবে না।

মাইক্রোসফ্ট ধারাবাহিকভাবে যারা নিয়ম লঙ্ঘন করে

ঠিক আছে, # 2 এবং # 3 যাইহোক। আমাদের প্রিয় অভিধান দুটি অভ্যন্তরীণ structs আছে:

[StructLayout(LayoutKind.Sequential)]  // default for structs
private struct Entry  //<Tkey, TValue>
{
    //  View code at *Reference Source
}

[Serializable, StructLayout(LayoutKind.Sequential)]
public struct Enumerator : 
    IEnumerator<KeyValuePair<TKey, TValue>>, IDisposable, 
    IDictionaryEnumerator, IEnumerator
{
    //  View code at *Reference Source
}

* রেফারেন্স উত্স

'JonnyCantCode.com' উত্স 4 টির মধ্যে 3 পেয়েছে - বেশিরভাগ ক্ষমাশীল # 4 সম্ভবত একটি সমস্যা হবে না। আপনি নিজেকে একটি বক্সিং একটি বক্সিং খুঁজে পেতে, আপনার স্থাপত্য পুনর্বিবেচনা।

দেখা যাক কেন মাইক্রোসফ্ট এই structs ব্যবহার করবে:

  1. প্রতিটি গঠন, Entry এবং Enumerator , একক মান প্রতিনিধিত্ব করে।
  2. গতি
  3. Entry অভিধান ক্লাসের বাইরে একটি পরামিতি হিসাবে পাস করা হয় না। আরও তদন্ত দেখায় যে অনিয়মিতের বাস্তবায়ন সন্তুষ্ট করার জন্য অভিধান অভিধানের গঠন ব্যবহার করে যা প্রতিবার একটি প্রতিবেদক অনুরোধ করে যখন এটি অনুলিপি করে ... বোঝায়।
  4. অভিধান ক্লাস অভ্যন্তরীণ। পরিসংখ্যান জনসাধারণ কারণ অভিধানটি সংখ্যাবহুল এবং IENumerator ইন্টারফেস বাস্তবায়ন সমান অ্যাক্সেসযোগ্যতা থাকতে হবে - যেমন IENumerator GETER।

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

আমরা এখানে দেখতে পাই না এমন কোনও প্রচেষ্টা বা প্রয়োজনীয় প্রমাণ যা structsগুলিকে অপ্রয়োজনীয় রাখতে বা শুধুমাত্র 16 বাইট বা তার কম একটি উদাহরণ আকার বজায় রাখতে পারে:

  1. উপরোক্ত structs কিছুই readonly ঘোষণা করা হয় - অপরিবর্তনীয় না
  2. এই কাঠামো আকার 16 বাইট উপর ভাল হতে পারে
  3. Entry একটি অনিশ্চিত জীবনকাল ( Add() থেকে Add() , Remove() , Clear() , বা আবর্জনা সংগ্রহ) আছে;

এবং ... 4. উভয় structs TKey এবং TValue সংরক্ষণ, যা আমরা সব জানি রেফারেন্স ধরনের হচ্ছে (যোগ যোগ বোনাস তথ্য)

হ্যাশেড কীগুলি সত্ত্বেও, অভিধানগুলি দ্রুত অংশে রয়েছে কারণ একটি স্ট্রাস্ট ইনস্ট্যান্স করা একটি রেফারেন্স টাইপের চেয়ে দ্রুত। এখানে, আমার একটি Dictionary<int, int> যা ক্রমবর্ধমান ক্রমবর্ধমান কীগুলির সাথে 300,000 র্যান্ডম পূর্ণসংখ্যা সঞ্চয় করে।

ক্যাপাসিটি: 312874
MemSize: 2660827 বাইট
সম্পূর্ণ আকার পরিবর্তন: 5 মি
পূরণ করার মোট সময়: 889 মি

ক্যাপাসিটি : অভ্যন্তরীণ অ্যারের আগে উপলব্ধ উপাদান সংখ্যা পুনরায় আকার করা আবশ্যক।

MemSize : অভিধানকে সিরিয়াসিয়ামে মেমরিস্ট্রিমে এবং বাইটের দৈর্ঘ্য (আমাদের উদ্দেশ্যের জন্য যথাযথ নির্ভুল) দ্বারা নির্ধারিত হয়।

সম্পূর্ণ আকার পরিবর্তন: 150862 উপাদানের থেকে অভ্যন্তরীণ অ্যারের আকারে 312874 উপাদানের আকার পরিবর্তন করা। যখন আপনি প্রতিটি উপাদান ক্রমবর্ধমান Array.CopyTo() অনুলিপি করা হয় যে চিত্র, যে খুব Array.CopyTo() নয়।

ভরাট করার জন্য মোট সময় : লগিংয়ের কারণে OnResize হয়েছে এবং আমি উৎসে যোগ করা একটি OnResize ইভেন্ট; যাইহোক, অপারেশন সময় 15 বার পুনরায় আকার যখন 300k পূর্ণসংখ্যা পূরণ করতে এখনও চিত্তাকর্ষক। শুধু কৌতূহল থেকে, আমি ইতিমধ্যে ক্ষমতা জানত যদি মোট সময় পূরণ করতে হবে? 13ms

সুতরাং, এখন, যদি Entry একটি শ্রেণী ছিল? এই বার বা ম্যাট্রিক্স সত্যিই যে অনেক পার্থক্য হবে?

ক্যাপাসিটি: 312874
MemSize: 2660827 বাইট
সম্পূর্ণ আকার পরিবর্তন: 26ms
পূরণ করার মোট সময়: 964ms

অবশ্যই, বড় পার্থক্য আকার পরিবর্তন করা হয়। অভিধানে কোনও পার্থক্য যদি ক্যাপাসিটি দিয়ে শুরু হয়? যথেষ্ট ... 12ms সঙ্গে উদ্বিগ্ন হতে।

কি ঘটেছে, কারণ Entry একটি struct, এটি একটি রেফারেন্স টাইপের মতো সূচনা প্রয়োজন হয় না। এই মান টাইপ সৌন্দর্য এবং বেন উভয় হয়। একটি রেফারেন্স টাইপ হিসাবে Entry ব্যবহার করার জন্য, আমাকে নিম্নলিখিত কোডটি ঢোকাতে হয়েছিল:

/*
 *  Added to satisfy initialization of entry elements --
 *  this is where the extra time is spent resizing the Entry array
 * **/
for (int i = 0 ; i < prime ; i++)
{
    destinationArray[i] = new Entry( );
}
/*  *********************************************** */  

একটি রেফারেন্স টাইপ হিসাবে Entry প্রতিটি অ্যারের উপাদান আরম্ভ করার কারণ আমি এমএসডিএন: কাঠামো ডিজাইন পাওয়া যাবে। সংক্ষেপে:

একটি গঠন জন্য একটি ডিফল্ট কনস্ট্রাক্টর প্রদান করবেন না।

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

কিছু কম্পাইলার, যেমন সি # কম্পাইলার, স্ট্রাকচারগুলিকে ডিফল্ট কন্সট্রকটর করার অনুমতি দেয় না।

এটা আসলে বেশ সহজ এবং আমরা রোবোটিক্সের আসিমভের তিনটি আইন থেকে ধার নেব:

  1. কাঠামো ব্যবহার করা নিরাপদ হতে হবে
  2. গঠনটি কার্যকরভাবে তার কার্য সম্পাদন করতে হবে, যদি না এটি # 1 নিয়ম লঙ্ঘন করে
  3. কাঠামোটি অবশ্যই তার ব্যবহারের সময় অক্ষত থাকা উচিত যতক্ষণ না তার ধ্বংসের নিয়ম # 1 পূরণ করতে হয়

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


পিনভোক উদ্দেশ্যে সরাসরি রানটাইম এবং অন্যান্যদের দ্বারা সরাসরি ব্যবহৃত মূল্যবোধের ব্যতিক্রম ব্যতীত, আপনাকে কেবল 2 টি পরিস্থিতিতেই মূল্যবোধগুলি ব্যবহার করতে হবে।

  1. যখন আপনি কপি semantics প্রয়োজন।
  2. যখন আপনি স্বয়ংক্রিয়ভাবে এই ধরনের অ্যারের মধ্যে স্বয়ংক্রিয় প্রাথমিককরণ প্রয়োজন।

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


রেফারেন্স সেমেটিক্সের বিরোধিতাকারী হিসাবে আপনি মান শব্দার্থবিদ্যা চান যখন একটি গঠন ব্যবহার করুন।

সম্পাদন করা

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

আপনি রেফারেন্স semantics প্রয়োজন হলে আপনি একটি বর্গ একটি কাঠ প্রয়োজন।


সি # ভাষা স্পেসিফিকেশন থেকে :

1.7 রেখাচিত্র

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

কাঠামো মূল্য semantics আছে ছোট তথ্য কাঠামো জন্য বিশেষভাবে দরকারী। কমপ্লেক্স সংখ্যার, একটি সমন্বয় সিস্টেমের মধ্যে পয়েন্ট, বা একটি অভিধানে কী-মান জোড়াগুলি হল structs এর সব ভাল উদাহরণ। ছোট তথ্য কাঠামোর জন্য ক্লাসের পরিবর্তে structs ব্যবহার একটি অ্যাপ্লিকেশন সঞ্চালন মেমরি বরাদ্দ সংখ্যা একটি বড় পার্থক্য করতে পারে। উদাহরণস্বরূপ, নিচের প্রোগ্রামটি 100 পয়েন্টের একটি অ্যারে তৈরি করে এবং সূচনা করে। বিন্দু হিসাবে প্রয়োগ করা পয়েন্ট সহ, 101 টি পৃথক বস্তু তাত্ক্ষণিকভাবে-অ্যারের জন্য এবং 100 টি উপাদানের জন্য প্রতিটি এক।

class Point
{
   public int x, y;

   public Point(int x, int y) {
      this.x = x;
      this.y = y;
   }
}

class Test
{
   static void Main() {
      Point[] points = new Point[100];
      for (int i = 0; i < 100; i++) points[i] = new Point(i, i);
   }
}

একটি বিকল্প পয়েন্ট গঠন করা হয়।

struct Point
{
   public int x, y;

   public Point(int x, int y) {
      this.x = x;
      this.y = y;
   }
}

এখন, শুধুমাত্র একটি বস্তু তাত্ক্ষণিক-অ্যারের জন্য একটি এবং পয়েন্ট দৃষ্টান্ত অ্যারের মধ্যে ইন-লাইন সংরক্ষণ করা হয়।

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

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

Point a = new Point(10, 10);
Point b = a;
a.x = 20;
Console.WriteLine(b.x);

যদি পয়েন্ট একটি বর্গ হয়, আউটপুট 20 কারণ একটি এবং বি একই বস্তুর উল্লেখ করে। যদি পয়েন্ট একটি struct হয়, আউটপুট 10 হয় কারণ a to b এর অ্যাসাইনমেন্ট মানটির একটি অনুলিপি তৈরি করে এবং এই অনুলিপিটি পরবর্তীতে অ্যাসাইনমেন্ট দ্বারা অকার্যকর হয়

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


আমার নিয়ম

1, সর্বদা ক্লাস ব্যবহার করুন;

2, যদি কোনো কর্মক্ষমতা সমস্যা থাকে, তবে আমি @Abbstract উল্লেখ করা নিয়মগুলির উপর নির্ভর করে কিছু ক্লাসকে স্ট্রাস্টে পরিবর্তন করার চেষ্টা করি এবং তারপর এই পরিবর্তনগুলি কর্মক্ষমতা উন্নত করতে পারে কিনা তা পরীক্ষা করার জন্য পরীক্ষা করে দেখুন।


আমি একটি ভাল প্রথম আনুমানিক "কখনও না" মনে হয়।

আমি মনে করি একটি ভাল দ্বিতীয় আনুমানিক "কখনও" হয়।

আপনি perf জন্য হতাশ হয়, তাদের বিবেচনা, কিন্তু তারপর সর্বদা পরিমাপ।


গঠন বা মান প্রকার নিম্নলিখিত পরিস্থিতিতে ব্যবহার করা যেতে পারে -

  1. আপনি আবর্জনা সংগ্রহ দ্বারা বস্তু সংগ্রহ করা প্রতিরোধ করতে চান।
  2. এটি একটি সাধারণ টাইপ এবং কোন সদস্য ফাংশন তার উদাহরণ ক্ষেত্র পরিবর্তন করে
  3. অন্যান্য ধরনের থেকে প্রাপ্ত বা অন্য ধরনের derived হচ্ছে কোন প্রয়োজন নেই।

আপনি এই লিঙ্কটিতে মানের ধরন এবং মূল্যের ধরন সম্পর্কে আরও জানতে পারেন


C # struct একটি ক্লাসের জন্য হালকা বিকল্প। এটি একটি শ্রেণির মতো প্রায় একই রকম করতে পারে, তবে এটি একটি শ্রেণির পরিবর্তে একটি স্ট্রাক ব্যবহার করার জন্য কম "ব্যয়বহুল"। এটির কারণটি একটি বিট প্রযুক্তিগত, তবে সমষ্টিগতভাবে, একটি শ্রেণির নতুন উদাহরণ হিপে স্থাপন করা হয়, যেখানে নতুন তাত্ক্ষণিক structs স্ট্যাকের উপর স্থাপন করা হয়। উপরন্তু, আপনি ক্লাসের মতো structs এর রেফারেন্সের সাথে ডিল করছেন না, বরং পরিবর্তে আপনি স্ট্রাস্ট ইনস্ট্যান্সের সাথে সরাসরি কাজ করছেন। এর অর্থ হল যে যখন আপনি একটি ফাংশনে একটি struct পাস করেন, এটি একটি রেফারেন্সের পরিবর্তে মান দ্বারা হয়। ফাংশন পরামিতি সম্পর্কে অধ্যায় এই সম্পর্কে আরো আছে।

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


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

উল্লেখ্য, কাঠামোটির ধরনটি ডিজাইন করা সম্ভব, যাতে এটি অবশ্যই ক্লাসের ধরনের মতো আচরণ করবে, যদি কাঠামোতে একটি ব্যক্তিগত ক্লাস-টাইপ ক্ষেত্র থাকে এবং তার নিজের সদস্যদের আবৃত শ্রেণিবদ্ধ বস্তুর সাথে পুনঃনির্দেশ করে। উদাহরণস্বরূপ, একটি PersonCollectionবৈশিষ্ট্য প্রস্তাব পারে SortedByNameএবং SortedByIdউভয় যার একটি থেকে একটি "অপরিবর্তনীয়" রেফারেন্স রাখা PersonCollection(তাদের কন্সট্রাকটর সেট) এবং বাস্তবায়ন GetEnumeratorকলিং হয় এর creator.GetNameSortedEnumeratorবা creator.GetIdSortedEnumerator। যেমন structs একটি রেফারেন্স মত অনেক আচরণ করবে PersonCollection, তাদের GetEnumeratorপদ্ধতি বিভিন্ন পদ্ধতির আবদ্ধ করা হবে না ছাড়া PersonCollection। এক একটি কাঠামো একটি অ্যারের একটি অংশ মোড়ানো (যেমন এক একটি সংজ্ঞায়িত করতে পারে হতে পারে ArrayRange<T>কাঠামো যা রাখা হবে T[]বলা Arr, কোন int Offset, এবং একটি int- এLength, সূচীকৃত সম্পত্তির সাথে, যা idxপরিসর 0 এর মধ্যে একটি সূচকের জন্য Length-1অ্যাক্সেস করবে Arr[idx+Offset])। দুর্ভাগ্যবশত, যদি fooএই ধরনের কাঠামোর কেবলমাত্র পাঠযোগ্য উদাহরণ হয় তবে বর্তমান কম্পাইলার সংস্করণগুলি এমন ক্রিয়াকলাপগুলিকে অনুমতি দেবে না foo[3]+=4;কারণ এগুলির ক্রিয়াকলাপ ক্ষেত্রগুলিতে লেখার চেষ্টা করবে কিনা তা নির্ধারণের কোনও উপায় নেই foo

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


আমি শুধু উইন্ডোজ কমিউনিকেশন ফাউন্ডেশন [WCF] নামযুক্ত পাইপ সঙ্গে তার আচরণ ছিল এবং আমি যে বিজ্ঞপ্তি এটা অনুক্রমে ব্যবহার structs ডেটার যে বিনিময় হয় তা নিশ্চিত করার জন্য জানার জন্য করেনি মান টাইপ পরিবর্তে রেফারেন্স টাইপ


আমি সঙ্গে একটি ছোট বেঞ্চমার্ক তৈরি BenchmarkDotNet সংখ্যায় "struct হয়" উপকার ভাল করে বুঝতে জন্য। আমি structs (বা ক্লাস) এর অ্যারে (বা তালিকা) মাধ্যমে looping পরীক্ষা করছি। সেই অ্যারে বা তালিকাগুলি তৈরি করা বেঞ্চমার্কের সুযোগের বাইরে - এটি স্পষ্ট যে "বর্গ" আরও বেশি মেমরি ব্যবহার করবে এবং এতে জিসি জড়িত হবে।

তাই উপসংহার হল: LINQ এবং লুকানো structs বক্সিং / unboxing এবং microoptimizations জন্য structs ব্যবহার কঠোরভাবে অ্যারে সঙ্গে থাকার সঙ্গে সতর্কতা অবলম্বন করা।

PS কল স্ট্যাকের মাধ্যমে স্ট্রাকচার / ক্লাস পাস করার আরেকটি বেঞ্চমার্ক https://.com/a/47864451/506147

BenchmarkDotNet=v0.10.8, OS=Windows 10 Redstone 2 (10.0.15063)
Processor=Intel Core i5-2500K CPU 3.30GHz (Sandy Bridge), ProcessorCount=4
Frequency=3233542 Hz, Resolution=309.2584 ns, Timer=TSC
  [Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.7.2101.1
  Clr    : Clr 4.0.30319.42000, 64bit RyuJIT-v4.7.2101.1
  Core   : .NET Core 4.6.25211.01, 64bit RyuJIT


          Method |  Job | Runtime |      Mean |     Error |    StdDev |       Min |       Max |    Median | Rank |  Gen 0 | Allocated |
---------------- |----- |-------- |----------:|----------:|----------:|----------:|----------:|----------:|-----:|-------:|----------:|
   TestListClass |  Clr |     Clr |  5.599 us | 0.0408 us | 0.0382 us |  5.561 us |  5.689 us |  5.583 us |    3 |      - |       0 B |
  TestArrayClass |  Clr |     Clr |  2.024 us | 0.0102 us | 0.0096 us |  2.011 us |  2.043 us |  2.022 us |    2 |      - |       0 B |
  TestListStruct |  Clr |     Clr |  8.427 us | 0.1983 us | 0.2204 us |  8.101 us |  9.007 us |  8.374 us |    5 |      - |       0 B |
 TestArrayStruct |  Clr |     Clr |  1.539 us | 0.0295 us | 0.0276 us |  1.502 us |  1.577 us |  1.537 us |    1 |      - |       0 B |
   TestLinqClass |  Clr |     Clr | 13.117 us | 0.1007 us | 0.0892 us | 13.007 us | 13.301 us | 13.089 us |    7 | 0.0153 |      80 B |
  TestLinqStruct |  Clr |     Clr | 28.676 us | 0.1837 us | 0.1534 us | 28.441 us | 28.957 us | 28.660 us |    9 |      - |      96 B |
   TestListClass | Core |    Core |  5.747 us | 0.1147 us | 0.1275 us |  5.567 us |  5.945 us |  5.756 us |    4 |      - |       0 B |
  TestArrayClass | Core |    Core |  2.023 us | 0.0299 us | 0.0279 us |  1.990 us |  2.069 us |  2.013 us |    2 |      - |       0 B |
  TestListStruct | Core |    Core |  8.753 us | 0.1659 us | 0.1910 us |  8.498 us |  9.110 us |  8.670 us |    6 |      - |       0 B |
 TestArrayStruct | Core |    Core |  1.552 us | 0.0307 us | 0.0377 us |  1.496 us |  1.618 us |  1.552 us |    1 |      - |       0 B |
   TestLinqClass | Core |    Core | 14.286 us | 0.2430 us | 0.2273 us | 13.956 us | 14.678 us | 14.313 us |    8 | 0.0153 |      72 B |
  TestLinqStruct | Core |    Core | 30.121 us | 0.5941 us | 0.5835 us | 28.928 us | 30.909 us | 30.153 us |   10 |      - |      88 B |

কোড:

[RankColumn, MinColumn, MaxColumn, StdDevColumn, MedianColumn]
    [ClrJob, CoreJob]
    [HtmlExporter, MarkdownExporter]
    [MemoryDiagnoser]
    public class BenchmarkRef
    {
        public class C1
        {
            public string Text1;
            public string Text2;
            public string Text3;
        }

        public struct S1
        {
            public string Text1;
            public string Text2;
            public string Text3;
        }

        List<C1> testListClass = new List<C1>();
        List<S1> testListStruct = new List<S1>();
        C1[] testArrayClass;
        S1[] testArrayStruct;
        public BenchmarkRef()
        {
            for(int i=0;i<1000;i++)
            {
                testListClass.Add(new C1  { Text1= i.ToString(), Text2=null, Text3= i.ToString() });
                testListStruct.Add(new S1 { Text1 = i.ToString(), Text2 = null, Text3 = i.ToString() });
            }
            testArrayClass = testListClass.ToArray();
            testArrayStruct = testListStruct.ToArray();
        }

        [Benchmark]
        public int TestListClass()
        {
            var x = 0;
            foreach(var i in testListClass)
            {
                x += i.Text1.Length + i.Text3.Length;
            }
            return x;
        }

        [Benchmark]
        public int TestArrayClass()
        {
            var x = 0;
            foreach (var i in testArrayClass)
            {
                x += i.Text1.Length + i.Text3.Length;
            }
            return x;
        }

        [Benchmark]
        public int TestListStruct()
        {
            var x = 0;
            foreach (var i in testListStruct)
            {
                x += i.Text1.Length + i.Text3.Length;
            }
            return x;
        }

        [Benchmark]
        public int TestArrayStruct()
        {
            var x = 0;
            foreach (var i in testArrayStruct)
            {
                x += i.Text1.Length + i.Text3.Length;
            }
            return x;
        }

        [Benchmark]
        public int TestLinqClass()
        {
            var x = testListClass.Select(i=> i.Text1.Length + i.Text3.Length).Sum();
            return x;
        }

        [Benchmark]
        public int TestLinqStruct()
        {
            var x = testListStruct.Select(i => i.Text1.Length + i.Text3.Length).Sum();
            return x;
        }
    }

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

ক্লাস এবং স্ট্রাক্টস (সি # প্রোগ্রামিং গাইড)


কাঠামো ক্লাস / বস্তু মত অধিকাংশ উপায়ে হয়। গঠন ফাংশন থাকতে পারে, সদস্য এবং উত্তরাধিকারী হতে পারে। কিন্তু কাঠামোগুলি সি # ধারণের জন্য ব্যবহৃত হয় । কাঠামোগুলি ক্লাসের চেয়ে কম র্যাম নেয় এবং আবর্জনা সংগ্রাহক সংগ্রহের জন্য সহজতর । কিন্তু যখন আপনি আপনার কাঠামোতে ফাংশনগুলি ব্যবহার করেন, তখন কম্পাইলারটি প্রকৃতপক্ষে ক্লাস / বস্তুর মতো একই কাঠামো নেয়, তাই যদি আপনি ফাংশনগুলির সাথে কিছু চান তবে ক্লাস / বস্তুটি ব্যবহার করুন


নাহ - আমি সম্পূর্ণরূপে নিয়ম সঙ্গে একমত না। তারা কর্মক্ষমতা এবং মানদণ্ডের সাথে বিবেচনা করার জন্য ভাল নির্দেশিকা, কিন্তু সম্ভাবনার আলোকে নয়।

আপনি প্রতিক্রিয়া দেখতে পারেন হিসাবে, তাদের ব্যবহার করার জন্য অনেক সৃজনশীল উপায় আছে। সুতরাং, এই নির্দেশিকাগুলির কেবলমাত্র কার্যকারিতা এবং দক্ষতার জন্য সবসময়ই প্রয়োজন।

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

আমি Treeview এবং Listview ট্যাগগুলিতে তাদের অনেকগুলি ব্যবহার করি যেখানে সাধারণ স্ট্যাটিক বৈশিষ্ট্যগুলি খুব দ্রুত অ্যাক্সেস করা যেতে পারে। আমি সবসময় এই তথ্য অন্য উপায় পেতে সংগ্রাম করেছেন। উদাহরণস্বরূপ, আমার ডাটাবেস অ্যাপ্লিকেশনগুলিতে, আমি একটি ট্রিউউউউ ব্যবহার করি যেখানে আমার টেবিল, এসপি, ফাংশন, বা অন্য কোনও বস্তু রয়েছে। আমি আমার struct তৈরি এবং populate, ট্যাগ মধ্যে এটি করা, এটি টান, নির্বাচন তথ্য পেতে এবং তাই ঘোষণা। আমি ক্লাসের সাথে এটা করব না!

আমি চেষ্টা করি এবং তাদের ছোট রাখি, একক পরিস্থিতিতে তাদের ব্যবহার করি, এবং পরিবর্তন থেকে তাদের রাখি। মেমরি, বরাদ্দকরণ, এবং কর্মক্ষমতা সচেতন হতে এটা বিচক্ষণ। এবং পরীক্ষার তাই প্রয়োজনীয়।





struct