সতর্কতা: এই প্রশ্নটি কিছুটা তাত্পর্যপূর্ণ ... ধর্মীয় প্রোগ্রামাররা সর্বদা ভাল অনুশীলনের প্রতি অনুগত হয়, দয়া করে এটি পড়বেন না। :)
কেউ কি জানেন যে কেন টাইপডেফারেন্সের ব্যবহার এতটা নিরুৎসাহিত হয় ( স্পষ্টতই , ডকুমেন্টের অভাবে)?
আমি এটির জন্য দুর্দান্ত ব্যবহারগুলি পেয়েছি যেমন যেমন জেনেরিক না হওয়া উচিত এমন ফাংশনগুলির মাধ্যমে জেনেরিক পরামিতিগুলি পাস করার সময় (যখন object
কোনও মান ধরণের প্রয়োজন হলে খুব বেশি পরিমাণে বা ধীর হতে পারে) তখন যখন আপনার অস্বচ্ছ পয়েন্টার প্রয়োজন হয়, বা কারণ যখন আপনার কোনও অ্যারের কোনও উপাদান দ্রুত অ্যাক্সেস করার দরকার হয়, যার স্পেসগুলি আপনি রানটাইমে খুঁজে পেয়েছেন (ব্যবহার করছেন Array.InternalGetReference
)। যেহেতু সিএলআর এই ধরণের ভুল ব্যবহারের অনুমতিও দেয় না, কেন এটি নিরুৎসাহিত করা হচ্ছে? এটি নিরাপদ বা অন্য কিছু বলে মনে হচ্ছে না ...
অন্যান্য ব্যবহার আমি খুঁজে পেয়েছি TypedReference
:
সি # তে জেনেরিকগুলি বিশেষজ্ঞকরণ (এটি টাইপ-নিরাপদ):
static void foo<T>(ref T value)
{
//This is the ONLY way to treat value as int, without boxing/unboxing objects
if (value is int)
{ __refvalue(__makeref(value), int) = 1; }
else { value = default(T); }
}
লিখিত কোড যা জেনেরিক পয়েন্টারগুলির সাথে কাজ করে (এটি অপব্যবহার করা হলে এটি খুব নিরাপদ তবে সঠিকভাবে ব্যবহার করা হলে দ্রুত এবং নিরাপদ):
//This bypasses the restriction that you can't have a pointer to T,
//letting you write very high-performance generic code.
//It's dangerous if you don't know what you're doing, but very worth if you do.
static T Read<T>(IntPtr address)
{
var obj = default(T);
var tr = __makeref(obj);
//This is equivalent to shooting yourself in the foot
//but it's the only high-perf solution in some cases
//it sets the first field of the TypedReference (which is a pointer)
//to the address you give it, then it dereferences the value.
//Better be 10000% sure that your type T is unmanaged/blittable...
unsafe { *(IntPtr*)(&tr) = address; }
return __refvalue(tr, T);
}
নির্দেশের একটি পদ্ধতি সংস্করণ লিখন sizeof
, যা মাঝে মধ্যে কার্যকর হতে পারে:
static class ArrayOfTwoElements<T> { static readonly Value = new T[2]; }
static uint SizeOf<T>()
{
unsafe
{
TypedReference
elem1 = __makeref(ArrayOfTwoElements<T>.Value[0] ),
elem2 = __makeref(ArrayOfTwoElements<T>.Value[1] );
unsafe
{ return (uint)((byte*)*(IntPtr*)(&elem2) - (byte*)*(IntPtr*)(&elem1)); }
}
}
এমন একটি পদ্ধতি লেখা যা "স্টেট" পরামিতি পাস করে যা বক্সিং এড়াতে চায়:
static void call(Action<int, TypedReference> action, TypedReference state)
{
//Note: I could've said "object" instead of "TypedReference",
//but if I had, then the user would've had to box any value types
try
{
action(0, state);
}
finally { /*Do any cleanup needed*/ }
}
তাহলে কেন এই "নিরুৎসাহিত" (ডকুমেন্টেশনের অভাবে) ব্যবহারের মতো? কোনও বিশেষ সুরক্ষার কারণ? এটি পুরোপুরি নিরাপদ এবং যাচাইযোগ্য মনে হচ্ছে যদি এটি পয়েন্টারগুলির সাথে মিশ্রিত না হয় (যা নিরাপদ বা যাচাইযোগ্য নয়) তবে ...
হালনাগাদ:
নমুনা কোডটি দেখানোর জন্য, প্রকৃতপক্ষে TypedReference
দ্বিগুণ দ্রুত (বা আরও) হতে পারে:
using System;
using System.Collections.Generic;
static class Program
{
static void Set1<T>(T[] a, int i, int v)
{ __refvalue(__makeref(a[i]), int) = v; }
static void Set2<T>(T[] a, int i, int v)
{ a[i] = (T)(object)v; }
static void Main(string[] args)
{
var root = new List<object>();
var rand = new Random();
for (int i = 0; i < 1024; i++)
{ root.Add(new byte[rand.Next(1024 * 64)]); }
//The above code is to put just a bit of pressure on the GC
var arr = new int[5];
int start;
const int COUNT = 40000000;
start = Environment.TickCount;
for (int i = 0; i < COUNT; i++)
{ Set1(arr, 0, i); }
Console.WriteLine("Using TypedReference: {0} ticks",
Environment.TickCount - start);
start = Environment.TickCount;
for (int i = 0; i < COUNT; i++)
{ Set2(arr, 0, i); }
Console.WriteLine("Using boxing/unboxing: {0} ticks",
Environment.TickCount - start);
//Output Using TypedReference: 156 ticks
//Output Using boxing/unboxing: 484 ticks
}
}
(সম্পাদনা করুন: আমি উপরের মাপদণ্ডটি সম্পাদনা করেছি, যেহেতু পোস্টের সর্বশেষ সংস্করণটি কোডের একটি ডিবাগ সংস্করণ ব্যবহার করেছে [আমি এটি প্রকাশে পরিবর্তন করতে ভুলে গিয়েছি]) এবং জিসির উপর কোনও চাপ রাখিনি This এই সংস্করণটি আরও কিছুটা বাস্তবসম্মত এবং আমার সিস্টেমে এটি TypedReference
গড়ে তিনগুণ বেশি দ্রুত faster
int
-> DockStyle
) এ অন্তর্নিহিত টাইপ typeালাই । এই বাক্সগুলি বাস্তবের জন্য, এবং প্রায় দশগুণ ধীর।
TypedReference: 203 ticks
,boxing/unboxing: 31 ticks
। আমি যা চেষ্টা করি তা নয় (টাইমিংয়ের বিভিন্ন উপায় সহ) বক্সিং / আনবক্সিং আমার সিস্টেমে এখনও দ্রুত।