আমি কয়েকটি সি # 7 লাইব্রেরিটি ValueTuple
বিচ্ছেদ করেছি এবং দেখেছি জেনেরিকগুলি ব্যবহার করা হচ্ছে। কি ValueTuples
এবং কেন Tuple
পরিবর্তে না ?
আমি কয়েকটি সি # 7 লাইব্রেরিটি ValueTuple
বিচ্ছেদ করেছি এবং দেখেছি জেনেরিকগুলি ব্যবহার করা হচ্ছে। কি ValueTuples
এবং কেন Tuple
পরিবর্তে না ?
উত্তর:
কি
ValueTuples
এবং কেনTuple
পরিবর্তে না ?
এ ValueTuple
হ'ল একটি কাঠামো যা মূল System.Tuple
শ্রেণীর মতো একটি টুপল প্রতিবিম্বিত করে ।
মধ্যে মূল পার্থক্য Tuple
এবং ValueTuple
আছেন:
System.ValueTuple
একটি মান প্রকার (স্ট্রাক্ট), অন্যদিকে System.Tuple
একটি রেফারেন্স টাইপ ( class
)। বরাদ্দ এবং জিসি চাপ সম্পর্কে কথা বলার সময় এটি অর্থবহ।System.ValueTuple
এটি কেবল একটি নয় struct
, এটি একটি পরিবর্তনীয় , এবং এগুলি ব্যবহার করার সময় একজনকে সতর্কতা অবলম্বন করা উচিত। System.ValueTuple
ক্ষেত্র হিসাবে যখন কোনও শ্রেণি একটি ক্ষেত্র ধারণ করে তখন কী ঘটে তা ভাবুন ।System.ValueTuple
বৈশিষ্ট্যের পরিবর্তে ক্ষেত্রগুলির মাধ্যমে এর আইটেমগুলি প্রকাশ করে।সি # 7 অবধি, টিপলগুলি ব্যবহার করা খুব সুবিধাজনক ছিল না। তাদের ক্ষেত্র নাম Item1
, Item2
সবচেয়ে অন্যান্য ভাষায় মত তাদের জন্য ইত্যাদি, এবং ভাষা সরবরাহকৃত নি সিনট্যাক্স চিনি না (পাইথন, Scala)।
.NET ভাষা নকশা দল যখন ভাষা স্তরে টিপলগুলি সংযুক্ত করার এবং সিনট্যাক্স চিনির সাথে তাদের যুক্ত করার সিদ্ধান্ত নিয়েছিল তখন একটি গুরুত্বপূর্ণ বিষয় ছিল পারফরম্যান্স। ValueTuple
মান ধরণের হওয়ার সাথে সাথে আপনি তাদের ব্যবহারের সময় জিসি চাপ এড়াতে পারবেন কারণ (বাস্তবায়নের বিশদ হিসাবে) এগুলি স্ট্যাকের জন্য বরাদ্দ দেওয়া হবে।
অতিরিক্তভাবে, struct
রানটাইম দ্বারা একটি স্বয়ংক্রিয় (অগভীর) সমতা শব্দার্থক পদার্থ পায়, যেখানে এটি class
হয় না। যদিও ডিজাইন দলটি নিশ্চিত করেছে যে টিউপলসের জন্য আরও বেশি অনুকূলিত সাম্যতা থাকবে, তাই এটির জন্য একটি কাস্টম সমতা কার্যকর করা হয়েছে।
এর নকশা নোটগুলিরTuples
একটি অনুচ্ছেদ এখানে দেওয়া হয়েছে :
কাঠামো বা শ্রেণি:
যেমনটি উল্লেখ করা হয়েছে, আমি
structs
তার চেয়ে দ্বিগুণ প্রকার তৈরির প্রস্তাব করছিclasses
, যাতে কোনও বরাদ্দ জরিমানা তাদের সাথে যুক্ত না হয়। এগুলি যথাসম্ভব হালকা হওয়া উচিত।যুক্তিযুক্তভাবে,
structs
আরও ব্যয়বহুল হয়ে উঠতে পারে, কারণ অ্যাসাইনমেন্টটি একটি বড় মানের অনুলিপি করে। সুতরাং যদি তাদের তৈরি হওয়ার চেয়ে অনেক বেশি নির্ধারিত করা হয়structs
তবে এটি একটি খারাপ পছন্দ হবে।তাদের খুব অনুপ্রেরণায়, যদিও, টিপলগুলি সংক্ষিপ্ত হয়। অংশগুলি সম্পূর্ণর চেয়ে বেশি গুরুত্বপূর্ণ হলে আপনি সেগুলি ব্যবহার করবেন। সুতরাং সাধারণ প্যাটার্নটি হ'ল এটি নির্মাণ, ফিরে আসা এবং তত্ক্ষণাত তাদের ডেকনস্ট্রাক্ট করা। এই পরিস্থিতিতে স্ট্রাক্টগুলি পরিষ্কারভাবে পছন্দসই।
স্ট্রাক্টের আরও অনেকগুলি সুবিধা রয়েছে যা নিম্নলিখিতগুলির মধ্যে সুস্পষ্ট হয়ে উঠবে।
আপনি সহজেই দেখতে পাবেন যে সাথে কাজ করা System.Tuple
খুব দ্রুতই অস্পষ্ট হয়ে যায়। উদাহরণস্বরূপ, বলুন আমাদের একটি পদ্ধতি রয়েছে যা একটি যোগফল এবং একটি এর গণনা গণনা করে List<Int>
:
public Tuple<int, int> DoStuff(IEnumerable<int> values)
{
var sum = 0;
var count = 0;
foreach (var value in values) { sum += value; count++; }
return new Tuple(sum, count);
}
প্রাপ্তির শেষে, আমরা এর সাথে শেষ করি:
Tuple<int, int> result = DoStuff(Enumerable.Range(0, 10));
// What is Item1 and what is Item2?
// Which one is the sum and which is the count?
Console.WriteLine(result.Item1);
Console.WriteLine(result.Item2);
আপনি যেভাবে নাম যুক্তিগুলিতে মান টিউপলগুলি ডিকনস্ট্রাক্ট করতে পারেন তা হ'ল বৈশিষ্ট্যের আসল শক্তি:
public (int sum, int count) DoStuff(IEnumerable<int> values)
{
var res = (sum: 0, count: 0);
foreach (var value in values) { res.sum += value; res.count++; }
return res;
}
এবং গ্রহণের শেষে:
var result = DoStuff(Enumerable.Range(0, 10));
Console.WriteLine($"Sum: {result.Sum}, Count: {result.Count}");
বা:
var (sum, count) = DoStuff(Enumerable.Range(0, 10));
Console.WriteLine($"Sum: {sum}, Count: {count}");
যদি আমরা আমাদের পূর্ববর্তী উদাহরণের আড়ালে নজর রাখি, আমরা ValueTuple
যখন কম্পাইলারটিকে ডিকনস্ট্রাক্ট করতে বলি তখন আমরা ঠিক দেখতে পাই যে সংকলকটি কীভাবে ব্যাখ্যা করছে :
[return: TupleElementNames(new string[] {
"sum",
"count"
})]
public ValueTuple<int, int> DoStuff(IEnumerable<int> values)
{
ValueTuple<int, int> result;
result..ctor(0, 0);
foreach (int current in values)
{
result.Item1 += current;
result.Item2++;
}
return result;
}
public void Foo()
{
ValueTuple<int, int> expr_0E = this.DoStuff(Enumerable.Range(0, 10));
int item = expr_0E.Item1;
int arg_1A_0 = expr_0E.Item2;
}
অভ্যন্তরীণভাবে, সংকলিত কোডটি ব্যবহার করে Item1
এবং Item2
, তবে আমরা একটি পচে যাওয়া টিউপল নিয়ে কাজ করার কারণে এগুলি সমস্ত আমাদের থেকে দূরে সরে যায়। নামযুক্ত আর্গুমেন্টের সাথে একটি টিপল এর সাথে টীকা দেওয়া হয় TupleElementNamesAttribute
। আমরা যদি পঁচন পরিবর্তনের পরিবর্তে একটি একক তাজা পরিবর্তনশীল ব্যবহার করি তবে আমরা পাই:
public void Foo()
{
ValueTuple<int, int> valueTuple = this.DoStuff(Enumerable.Range(0, 10));
Console.WriteLine(string.Format("Sum: {0}, Count: {1})", valueTuple.Item1, valueTuple.Item2));
}
নোট কম্পাইলার এখনও কিছু জাদু ঘটতে (অনুষঙ্গ এর মাধ্যমে) যখন আমরা আমাদের অ্যাপ্লিকেশন ডিবাগ, যেমন এটি দেখতে অদ্ভুত হবে করতে আছে Item1
, Item2
।
var (sum, count) = DoStuff(Enumerable.Range(0, 10));
মধ্যে পার্থক্য Tuple
এবং ValueTuple
যে Tuple
একটি রেফারেন্স টাইপ করতে হবে এবং ValueTuple
একটি মান প্রকার। দ্বিতীয়টি পছন্দসই কারণ সি # 7 এর ভাষার পরিবর্তনের ক্ষেত্রে টিপলগুলি প্রায়শই ঘন ঘন ব্যবহৃত হয় তবে প্রতিটি টিপলের জন্য স্তূপে একটি নতুন অবজেক্ট বরাদ্দ করা একটি পারফরম্যান্স উদ্বেগ, বিশেষত যখন এটি অপ্রয়োজনীয়।
যাইহোক, সি # 7, যা এই ধারণার আপনি কখনই যে আছে স্পষ্টভাবে সিনট্যাক্স চিনি tuple ব্যবহারের জন্য যোগ করা হচ্ছে, কারণ এই দুই ধরনের যেকোন ব্যবহার করতে। উদাহরণস্বরূপ, সি # 6 এ, আপনি যদি কোনও মান ফেরত দেওয়ার জন্য একটি টুপল ব্যবহার করতে চান, আপনাকে নিম্নলিখিতগুলি করতে হবে:
public Tuple<string, int> GetValues()
{
// ...
return new Tuple(stringVal, intVal);
}
var value = GetValues();
string s = value.Item1;
তবে, সি # 7 এ আপনি এটি ব্যবহার করতে পারেন:
public (string, int) GetValues()
{
// ...
return (stringVal, intVal);
}
var value = GetValues();
string s = value.Item1;
আপনি আরও একধাপ এগিয়ে যেতে পারেন এবং মানগুলির নাম দিতে পারেন:
public (string S, int I) GetValues()
{
// ...
return (stringVal, intVal);
}
var value = GetValues();
string s = value.S;
... অথবা পুরোপুরি টিপলটি ডিকনস্ট্রাক্ট করুন:
public (string S, int I) GetValues()
{
// ...
return (stringVal, intVal);
}
var (S, I) = GetValues();
string s = S;
টিপলগুলি প্রায়শই সি # প্রাক -7 এ ব্যবহৃত হত না কারণ এগুলি জটিল এবং ভার্বোজ ছিল এবং কেবলমাত্র এমন ক্ষেত্রে ব্যবহৃত হয় যেখানে কাজের জন্য কেবলমাত্র একক উদাহরণের জন্য ডেটা শ্রেণি / কাঠামো তৈরি করা তার পক্ষে মূল্যমানের চেয়ে বেশি ঝামেলা হতে পারে। তবে সি # 7 এ, টিপলগুলির এখন ভাষা-স্তরের সমর্থন রয়েছে, সুতরাং এগুলি ব্যবহার করা অনেক বেশি পরিষ্কার এবং আরও কার্যকর।
আমি উভয় জন্য উৎস দিকে তাকিয়ে Tuple
এবং ValueTuple
। পার্থক্য হল Tuple
একটি হল class
এবং ValueTuple
একটি হল struct
যে কার্যকরী IEquatable
।
এটার মানে হল যে Tuple == Tuple
ফিরে আসবে false
যদি তারা একই উদাহরণস্বরূপ হয় না, কিন্তু ValueTuple == ValueTuple
ফিরে আসবে true
যদি তারা একই ধরনের এবং হয় Equals
আয় true
মান সেগুলির মধ্যে উপস্থিত প্রত্যেকের জন্য।
অন্যান্য উত্তরগুলি গুরুত্বপূর্ণ পয়েন্টগুলি উল্লেখ করতে ভুলে গেছে rep পুনরায় ব্যবহারের পরে, আমি উত্স কোড থেকে এক্সএমএল ডকুমেন্টেশনটি উল্লেখ করতে চাই :
মান 0 থেকে 8 টির মধ্যে রানটাইম বাস্তবায়ন যা সি # তে টিপলস এবং এফ # তে স্ট্রাক্ট টিপলসকে অন্তর্ভুক্ত করে।
ভাষার সিনট্যাক্সের মাধ্যমে তৈরি বাদে এগুলি ValueTuple.Create
কারখানার পদ্ধতিগুলির মাধ্যমে খুব সহজেই তৈরি করা হয়
। System.ValueTuple
ধরনের থেকে পৃথক System.Tuple
যে প্রকারসমূহ:
এই ধরণের এবং সি # 7.0 সংকলক প্রবর্তনের সাথে আপনি সহজেই লিখতে পারেন
(int, string) idAndName = (1, "John");
এবং একটি পদ্ধতি থেকে দুটি মান ফেরত দিন:
private (int, string) GetIdAndName()
{
//.....
return (id, name);
}
এর বিপরীতে আপনি System.Tuple
এর সদস্যদের আপডেট করতে পারবেন (পরিবর্তনযোগ্য) কারণ তারা সর্বজনীন পঠন-লিখনের ক্ষেত্র যা অর্থপূর্ণ নাম দেওয়া যেতে পারে:
(int id, string name) idAndName = (1, "John");
idAndName.name = "New Name";
class MyNonGenericType : MyGenericType<string, ValueTuple, int>
ইত্যাদি ইত্যাদি
উপরের মতামত ছাড়াও, ভ্যালুটিপল এর একটি দুর্ভাগ্যজনক গোটাচা হ'ল, মানের ধরণ হিসাবে, আইএল-এ সংকলিত হয়ে নাম যুক্তিগুলি মুছে ফেলা হয়, সুতরাং রানটাইমগুলিতে সেগুলি সিরিয়ালাইজেশনের জন্য উপলব্ধ নয়।
যেমন আপনার মিষ্টি নামের যুক্তিগুলি এখনও আইসন.এনইটি-র মাধ্যমে ক্রমিকায়িত করার পরে "আইটেম 1", "আইটেম 2" ইত্যাদি হিসাবে শেষ হবে।
এই দুটি ফ্যাক্টয়েডগুলির বিষয়ে একটি দ্রুত ব্যাখ্যা যোগ করতে দেরীতে যোগদান:
কেউ ভাবেন যে মান-টিপলস-এ-ম্যাসে পরিবর্তন করা সোজা হবে:
foreach (var x in listOfValueTuples) { x.Foo = 103; } // wont even compile because x is a value (struct) not a variable
var d = listOfValueTuples[0].Foo;
কেউ এ জাতীয়ভাবে চেষ্টা করার চেষ্টা করতে পারে:
// initially *.Foo = 10 for all items
listOfValueTuples.Select(x => x.Foo = 103);
var d = listOfValueTuples[0].Foo; // 'd' should be 103 right? wrong! it is '10'
এই উদ্বিগ্ন আচরণের কারণ হ'ল মান-টিপলস হুবহু মান-ভিত্তিক (স্ট্রাক্ট) এবং সুতরাং .সलेक्ट (...) কলটি মূলগুলির পরিবর্তে ক্লোনড-স্ট্রাক্টগুলিতে কাজ করে। এটি সমাধান করার জন্য আমাদের অবশ্যই অবলম্বন করতে হবে:
// initially *.Foo = 10 for all items
listOfValueTuples = listOfValueTuples
.Select(x => {
x.Foo = 103;
return x;
})
.ToList();
var d = listOfValueTuples[0].Foo; // 'd' is now 103 indeed
বিকল্পভাবে অবশ্যই একটি সহজ পদ্ধতির চেষ্টা করতে পারে:
for (var i = 0; i < listOfValueTuples.Length; i++) {
listOfValueTuples[i].Foo = 103; //this works just fine
// another alternative approach:
//
// var x = listOfValueTuples[i];
// x.Foo = 103;
// listOfValueTuples[i] = x; //<-- vital for this alternative approach to work if you omit this changes wont be saved to the original list
}
var d = listOfValueTuples[0].Foo; // 'd' is now 103 indeed
আশা করি এটি কাউকে তালিকা-হোস্ট করা মান-টিপলগুলি থেকে লেজের মাথা তৈরি করতে লড়াই করতে সহায়তা করবে।