আমি জানি যে .NET এ স্ট্রাইকগুলি উত্তরাধিকারকে সমর্থন করে না, তবে তারা কেন এইভাবে সীমাবদ্ধ তা ঠিক পরিষ্কার নয় ।
কোন প্রযুক্তিগত কারণে স্ট্র্টকে অন্য স্ট্রাক্ট থেকে উত্তরাধিকার সূত্রে বাধা দেয়?
আমি জানি যে .NET এ স্ট্রাইকগুলি উত্তরাধিকারকে সমর্থন করে না, তবে তারা কেন এইভাবে সীমাবদ্ধ তা ঠিক পরিষ্কার নয় ।
কোন প্রযুক্তিগত কারণে স্ট্র্টকে অন্য স্ট্রাক্ট থেকে উত্তরাধিকার সূত্রে বাধা দেয়?
উত্তর:
মূল্যের ধরণগুলি উত্তরাধিকারকে সমর্থন করতে পারে না তার কারণ অ্যারে of
সমস্যাটি হ'ল পারফরম্যান্স এবং জিসি কারণে, মান ধরণের অ্যারেগুলি "ইনলাইন" সংরক্ষণ করা হয়। উদাহরণস্বরূপ, প্রদত্ত new FooType[10] {...}
, যদি FooType
কোনও রেফারেন্স টাইপ হয় তবে পরিচালিত হিপগুলিতে 11 টি অবজেক্ট তৈরি করা হবে (অ্যারের জন্য একটি, এবং প্রতিটি টাইপের উদাহরণের জন্য 10)। FooType
পরিবর্তে যদি মান ধরণের হয় তবে পরিচালিত হিপগুলিতে কেবল একটি উদাহরণ তৈরি করা হবে - অ্যারে নিজেই (যেমন প্রতিটি অ্যারের মান অ্যারের সাথে "ইনলাইন" সংরক্ষণ করা হবে)।
এখন, ধরুন আমাদের মান ধরণের সাথে উত্তরাধিকার ছিল। উপরের "ইনলাইন স্টোরেজ" অ্যারের আচরণের সাথে একত্রিত হলে, খারাপ জিনিসগুলি ঘটে, যেমনটি সি ++ তে দেখা যায় ।
এই সিডো-সি # কোডটি বিবেচনা করুন:
struct Base
{
public int A;
}
struct Derived : Base
{
public int B;
}
void Square(Base[] values)
{
for (int i = 0; i < values.Length; ++i)
values [i].A *= 2;
}
Derived[] v = new Derived[2];
Square (v);
সাধারণ রূপান্তর নিয়ম অনুসারে, Derived[]
এটিকে একটি Base[]
(আরও ভাল বা খারাপের জন্য) রূপান্তরযোগ্য , সুতরাং আপনি যদি উপরের উদাহরণের জন্য s / স্ট্রাক্ট / শ্রেণি / জি হন তবে এটি কোনও সমস্যা ছাড়াই সংকলন এবং প্রত্যাশার মতো চলবে। তবে Base
এবং Derived
যদি মান ধরণের হয় এবং অ্যারে স্টোরের মানগুলিকে ইনলাইন করে থাকে তবে আমাদের সমস্যা আছে।
আমাদের একটি সমস্যা আছে কারণ এটি Square()
সম্পর্কে কিছুই জানে না Derived
, এটি অ্যারের প্রতিটি উপাদান অ্যাক্সেসের জন্য কেবলমাত্র পয়েন্টার গাণিতিক ব্যবহার করবে, ধ্রুবক পরিমাণে ( sizeof(A)
) বাড়িয়ে দেবে । সমাবেশটি অস্পষ্টভাবে হবে:
for (int i = 0; i < values.Length; ++i)
{
A* value = (A*) (((char*) values) + i * sizeof(A));
value->A *= 2;
}
(হ্যাঁ, এটি ঘৃণ্য সমাবেশ, তবে মূল বিষয়টি হ'ল আমরা কোনও সংগ্রহিত টাইম ব্যবহার করা হচ্ছে তার কোনও জ্ঞান ছাড়াই, পরিচিত সংকলন-সময় ধ্রুবকগুলিতে অ্যারের মাধ্যমে বৃদ্ধি করব))
সুতরাং, যদি এটি প্রকৃতপক্ষে ঘটে থাকে তবে আমাদের মেমরির দুর্নীতির সমস্যা হবে। বিশেষ করে, মধ্যে Square()
, values[1].A*=2
হবে আসলে পরিবর্তন হতে values[0].B
!
ডিবাগ করার চেষ্টা করুন যে !
স্ট্রাক্ট সমর্থিত উত্তরাধিকারের কল্পনা করুন। তারপরে ঘোষণা:
BaseStruct a;
InheritedStruct b; //inherits from BaseStruct, added fields, etc.
a = b; //?? expand size during assignment?
স্ট্রাক্ট ভেরিয়েবলের স্থির আকারের অর্থ হবে না এবং তাই আমাদের রেফারেন্সের ধরণ রয়েছে।
আরও ভাল, এটি বিবেচনা করুন:
BaseStruct[] baseArray = new BaseStruct[1000];
baseArray[500] = new InheritedStruct(); //?? morph/resize the array?
Foo
উত্তরাধিকারী হওয়ার কারণে একটিকে Bar
একটি Foo
বরাদ্দ দেওয়া উচিত নয় Bar
, তবে কাঠামোটি সেভাবে ঘোষণা করা কয়েক কার্যকর উপকারের অনুমতি দিতে পারে : (1) Bar
প্রথম আইটেম হিসাবে বিশেষভাবে নামযুক্ত সদস্য তৈরি করুন Foo
এবং Foo
এতে অন্তর্ভুক্ত থাকতে হবে সদস্যদের নাম যা সেই সদস্যদের মধ্যে উপন্যাস , সমস্ত রেফারেন্সের সাথে প্রতিস্থাপন না করে , এবং পরিবর্তে একটি গ্রুপ হিসাবে সমস্ত ক্ষেত্র পড়তে এবং লেখার দক্ষতা বজায় রেখে Bar
কোডটি পরিবর্তে ব্যবহার Bar
করার জন্য অভিযোজিত কোডকে অনুমতি দেয় ; ...Foo
thing.BarMember
thing.theBar.BarMember
Bar
স্ট্রাইকগুলি রেফারেন্স ব্যবহার করে না (যদি না সে বাক্স না হয় তবে আপনার এড়াতে চেষ্টা করা উচিত) সুতরাং বহুগুণবাদ অর্থবহ নয় কারণ কোনও রেফারেন্স পয়েন্টারের মাধ্যমে কোনও নির্দেশনা নেই। অবজেক্টগুলি সাধারণত গাদা হয়ে থাকে এবং রেফারেন্স পয়েন্টারগুলির মাধ্যমে রেফারেন্স করা হয় তবে স্ট্রাকের উপর স্ট্রোকগুলি বরাদ্দ করা হয় (যদি না তা বক্স না করা হয়) বা স্তূপের উপর রেফারেন্স টাইপের দ্বারা দখল করা মেমরিটিকে "ভিতরে" বরাদ্দ করা হয়।
Foo
যা কাঠামোর ধরণের Bar
ক্ষেত্রের Bar
সদস্যদের নিজস্ব হিসাবে বিবেচনা করতে সক্ষম হবে , যাতে একটি Point3d
ক্লাস যেমন একটি encapsulate Point2d xy
করতে পারে তবে X
ক্ষেত্রটির হয় হয় xy.X
বা হিসাবে উল্লেখ করুন X
।
ডক্স যা বলে তা এখানে :
স্ট্রাক্টগুলি বিশেষত ছোট ডেটা স্ট্রাকচারের জন্য দরকারী যার মূল্য শব্দার্থ রয়েছে। জটিল সংখ্যা, একটি সমন্বয় ব্যবস্থাতে পয়েন্ট বা অভিধানে কী-মান জোড়গুলি স্ট্রাক্টের ভাল উদাহরণ good এই ডেটা স্ট্রাকচারগুলির মূল কীটি হ'ল তাদের কয়েকটি ডেটা সদস্য রয়েছে, তাদের উত্তরাধিকার বা রেফারেনশিয়াল পরিচয় ব্যবহারের প্রয়োজন হয় না, এবং অ্যাসাইনমেন্টটি রেফারেন্সের পরিবর্তে মানটি অনুলিপি করে যেখানে সেগুলি সহজেই প্রয়োগ করা যেতে পারে।
মূলত, তাদের সাধারণ ডেটা রাখার কথা এবং তাই উত্তরাধিকারের মতো "অতিরিক্ত বৈশিষ্ট্যগুলি" নেই। তাদের পক্ষে কিছু সীমিত ধরণের উত্তরাধিকারকে সমর্থন করা প্রযুক্তিগতভাবে সম্ভব হবে (পলিমারফিজম নয়, তাদের স্ট্যাকের কারণে রয়েছে), তবে আমি বিশ্বাস করি যে উত্তরাধিকারকে সমর্থন না করার জন্য এটি একটি নকশা পছন্দও রয়েছে (নেট। নেট আরও অনেকগুলি জিনিস) ভাষা হয়।)
অন্যদিকে, আমি উত্তরাধিকারের সুবিধার সাথে একমত এবং আমি মনে করি আমরা সকলেই এমন এক জায়গায় পৌঁছেছি যেখানে আমরা struct
অন্যের কাছ থেকে উত্তরাধিকার পেতে চাই এবং বুঝতে পারি যে এটি সম্ভব নয়। তবে সেই সময়ে, ডেটা কাঠামো সম্ভবত এত উন্নত যে এটি যাইহোক একটি শ্রেণি হওয়া উচিত।
Point3D
থেকে একটি তৈরি করা Point2D
; আপনি সক্ষম হবেন না) এর Point3D
পরিবর্তে একটি ব্যবহার করতে Point2D
, তবে আপনাকে Point3D
পুরোপুরি স্ক্র্যাচ থেকে পুনরায় সংশোধন করতে হবে না )) আমি যেভাবেই এটির ব্যাখ্যা করব ...
class
ওভার struct
উপযুক্ত ক্ষেত্রে।
উত্তরাধিকারের মতো শ্রেণি সম্ভব নয়, কারণ সরাসরি স্ট্যাকের উপর একটি কাঠামো স্থাপন করা হয়। উত্তরাধিকার সূত্রে স্ট্রাক্ট বড় হবে তবে এটি পিতামাতার, তবে জেআইটি তা জানে না এবং খুব কম জায়গায় খুব বেশি পরিমাণে রাখার চেষ্টা করে। কিছুটা অস্পষ্ট মনে হচ্ছে, আসুন একটি উদাহরণ লিখি:
struct A {
int property;
} // sizeof A == sizeof int
struct B : A {
int childproperty;
} // sizeof B == sizeof int * 2
যদি এটি সম্ভব হয় তবে এটি নিম্নলিখিত স্নিপেটে ক্রাশ হবে:
void DoSomething(A arg){};
...
B b;
DoSomething(b);
স্থান খ এর আকারের জন্য বরাদ্দ করা হয়, বি আকারের জন্য নয় B.
আমি ঠিক করতে চাই একটি পয়েন্ট আছে। যদিও স্ট্রাক্টগুলি উত্তরাধিকার সূত্রে প্রাপ্ত হতে পারে না কারণ তারা স্ট্যাকের উপরে বাস করে সঠিক হ'ল, এটি একই অর্ধ সঠিক ব্যাখ্যা। স্ট্রাকস, অন্য যে কোনও মানের ধরণের মতো স্ট্যাকটিতে বাস করতে পারে । কারণ এটা উপর নির্ভর করবে যেখানে পরিবর্তনশীল ঘোষিত হয় তারা পারেন বাঁচবে স্ট্যাকের বা গাদা । এটি যখন যথাক্রমে স্থানীয় ভেরিয়েবল বা উদাহরণ ক্ষেত্র হয় This
এই বলে, সিসিলের একটি নাম এটি সঠিকভাবে পেরেক করেছে।
আমি এই জোর দেওয়া চাই, মান ধরনের পারেন স্ট্যাক বাস। এর অর্থ এই নয় যে তারা সর্বদা এটি করে। পদ্ধতি প্যারামিটার সহ স্থানীয় ভেরিয়েবলগুলি। অন্য সব না। যাইহোক, এটি এখনও উত্তরাধিকারসূত্রে প্রাপ্ত হওয়ার কারণ নেই। :-)
স্ট্যাকের উপর স্ট্রোকগুলি বরাদ্দ করা হয়। এর অর্থ মান শব্দার্থকগুলি বেশ নিখরচায় এবং স্ট্রাক্ট সদস্যদের অ্যাক্সেস করা খুব সস্তা। এটি পলিমারফিজম প্রতিরোধ করে না।
আপনি প্রতিটি ভার্চুয়াল ফাংশন টেবিলের পয়েন্টার দিয়ে শুরু করতে পারেন। এটি একটি পারফরম্যান্স ইস্যু হবে (প্রতিটি স্ট্রাক্ট কমপক্ষে একটি পয়েন্টারের আকার হবে) তবে এটি কার্যক্ষম। এটি ভার্চুয়াল ফাংশনগুলির অনুমতি দেবে।
ক্ষেত্র যুক্ত সম্পর্কে কি?
ঠিক আছে, আপনি যখন স্ট্যাকের উপর একটি কাঠামো বরাদ্দ করেন, আপনি একটি নির্দিষ্ট পরিমাণ জায়গা বরাদ্দ করেন। প্রয়োজনীয় স্থানটি সংকলনের সময় নির্ধারিত হয় (সময়ের আগে বা জেআইটিটিংয়ের সময়)। যদি আপনি ক্ষেত্রগুলি যুক্ত করেন এবং তারপরে একটি বেস প্রকারের জন্য বরাদ্দ করেন:
struct A
{
public int Integer1;
}
struct B : A
{
public int Integer2;
}
A a = new B();
এটি স্ট্যাকের কিছু অজানা অংশ ওভাররাইট করবে।
বিকল্পটি হ'ল রানটাইমটির জন্য এটি রোধ করার জন্য কেবলমাত্র কোনও এ ভেরিয়েবলের মাপের (এ) বাইট লিখে prevent
বি যদি এ এর কোনও পদ্ধতিকে ওভাররাইড করে এবং এর পূর্ণসংখ্যা 2 ক্ষেত্রের উল্লেখ করে তবে কী হবে? হয় রানটাইম একটি সদস্যঅ্যাক্সেস এক্সেপশন নিক্ষেপ করে, বা পদ্ধতিটি পরিবর্তে স্ট্যাকের কিছু এলোমেলো ডেটা অ্যাক্সেস করে। এগুলির কোনওটিই জায়েজ নয়।
কাঠামোগত উত্তরাধিকার রাখা এটি পুরোপুরি নিরাপদ, যতক্ষণ আপনি বহুত্বপূর্ণভাবে স্ট্রাইক ব্যবহার করবেন না, বা উত্তরাধিকার সূত্রে আপনি ক্ষেত্রগুলি যুক্ত করবেন না ততক্ষণ। তবে এগুলি ভয়াবহভাবে কার্যকর নয়।
এটি খুব ঘন ঘন একটি প্রশ্নের মতো মনে হচ্ছে। আমি মনে করি যে মানের প্রকারগুলি "জায়গায়" সঞ্চিত আছে যেখানে আপনি ভেরিয়েবলটি ঘোষণা করেন; বাস্তবায়নের বিশদগুলি বাদ দিয়ে এর অর্থ হ'ল কোনও অবজেক্ট শিরোনাম নেই যা অবজেক্ট সম্পর্কে কিছু বলে, কেবল ভেরিয়েবল জানে যে সেখানে কোন ধরণের ডেটা থাকে।
স্ট্রাইকগুলি সমর্থন ইন্টারফেস করে, যাতে আপনি কিছু পলিমারফিক জিনিসগুলি সেভাবে করতে পারেন।
আইএল একটি স্ট্যাক-ভিত্তিক ভাষা, সুতরাং যুক্তি সহ একটি পদ্ধতি কল করা এরকম কিছু হয়:
পদ্ধতিটি চললে, এটি যুক্তি পেতে স্ট্যাকের বাইরে কিছু বাইট পপ করে। এটা ঠিক জানে কতটা বাইট পপ অফ করতে কারণ আর্গুমেন্টটি একটি রেফারেন্স টাইপ পয়েন্টার (সর্বদা 4-বাইটে 32-বিট) বা এটি একটি মান ধরণের যার জন্য আকার সর্বদা সঠিকভাবে পরিচিত is
যদি এটি একটি রেফারেন্স টাইপ পয়েন্টার হয় তবে পদ্ধতিটি গাদা বস্তুটি দেখায় এবং তার টাইপ হ্যান্ডেলটি পেয়ে যায়, যা কোনও পদ্ধতির টেবিলের দিকে নির্দেশ করে যা সেই নির্দিষ্ট পদ্ধতির জন্য সেই নির্দিষ্ট পদ্ধতিটি পরিচালনা করে। যদি এটি মান ধরণের হয় তবে কোনও পদ্ধতির টেবিলের জন্য কোনও অনুসন্ধানের প্রয়োজন নেই কারণ মান প্রকারগুলি উত্তরাধিকার সমর্থন করে না, সুতরাং কেবলমাত্র একটি সম্ভাব্য পদ্ধতি / প্রকারের সমন্বয় রয়েছে।
যদি মানের ধরণগুলি উত্তরাধিকার হিসাবে সমর্থিত হয় তবে নির্দিষ্ট ধরণের কাঠামোর স্ট্যাকের পাশাপাশি তার মানের উপরে অতিরিক্ত ওভারহেড থাকতে হবে, যার অর্থ এই ধরণের নির্দিষ্ট কংক্রিটের উদাহরণের জন্য কোনও ধরণের পদ্ধতি টেবিল দেখার দরকার। এটি মান ধরণের গতি এবং দক্ষতা সুবিধাগুলি মুছে ফেলবে।