লাইনের নীচে উত্তরটি ২০০৮ সালে লেখা হয়েছিল।
সি # 7 প্রবর্তিত প্যাটার্ন ম্যাচিং, যা as
অপারেটরটিকে ব্যাপকভাবে প্রতিস্থাপন করেছে , আপনি এখন যেমন লিখতে পারেন:
if (randomObject is TargetType tt)
{
// Use tt here
}
মনে রাখবেন যে tt
এটির পরেও সুযোগ রয়েছে, তবে অবশ্যই নির্ধারিত নয়। (এটা হয় স্পষ্টভাবে মধ্যে নির্ধারিত if
শরীর।) কিছু ক্ষেত্রে সামান্য বিরক্তিকর, তাই আপনি যদি সত্যিই যে সুযোগ সম্ভাব্য ভেরিয়েবল সবচেয়ে ছোট সংখ্যা প্রবর্তনের যত্নশীল, আপনি কি এখনও ব্যবহার করতে চাইতে পারেন is
একটি ঢালাই করে।
আমার মনে হয় না এ পর্যন্ত যে কোনও উত্তর (উত্তরটি শুরু করার সময়!) সত্যই ব্যাখ্যা করেছে যে এটি কোনটি ব্যবহার করার পক্ষে উপযুক্ত।
এটি করবেন না:
// Bad code - checks type twice for no reason
if (randomObject is TargetType)
{
TargetType foo = (TargetType) randomObject;
// Do something with foo
}
এটি কেবল দুটিবার যাচাই করা নয়, এটি randomObject
স্থানীয় ভেরিয়েবলের চেয়ে ক্ষেত্র যদি হয় তবে এটি বিভিন্ন জিনিসও চেক করতে পারে । "যদি" পাস করা সম্ভব হয় তবে কাস্ট ব্যর্থ হতে পারে, যদি অন্য থ্রেডের randomObject
মধ্যে দুটির মান পরিবর্তন হয় ।
যদি randomObject
সত্যিই উদাহরণস্বরূপ হওয়া উচিতTargetType
, যদি তা না হয় তবে এর অর্থ একটি বাগ রয়েছে, তবে castালাই সঠিক সমাধান। এটি অবিলম্বে একটি ব্যতিক্রম ছোঁড়ে, যার অর্থ ভুল অনুমানের অধীনে আর কোনও কাজ করা হয় না এবং ব্যতিক্রমটি সঠিকভাবে বাগের ধরণটি দেখায়।
// This will throw an exception if randomObject is non-null and
// refers to an object of an incompatible type. The cast is
// the best code if that's the behaviour you want.
TargetType convertedRandomObject = (TargetType) randomObject;
যদি এটির উদাহরণ randomObject
হতে পারে TargetType
এবং TargetType
একটি রেফারেন্স টাইপ হয়, তবে এই জাতীয় কোড ব্যবহার করুন:
TargetType convertedRandomObject = randomObject as TargetType;
if (convertedRandomObject != null)
{
// Do stuff with convertedRandomObject
}
যদি এটির উদাহরণ randomObject
হতে পারে TargetType
এবং TargetType
মান ধরণের হয় তবে আমরা নিজের as
সাথে এটি ব্যবহার করতে পারি না TargetType
, তবে আমরা একটি প্রচ্ছন্ন প্রকারটি ব্যবহার করতে পারি:
TargetType? convertedRandomObject = randomObject as TargetType?;
if (convertedRandomObject != null)
{
// Do stuff with convertedRandomObject.Value
}
(দ্রষ্টব্য: বর্তমানে এটি + কাস্টের চেয়ে আসলে ধীর গতিযুক্ত I আমি মনে করি এটি আরও মার্জিত এবং ধারাবাহিক, তবে আমরা সেখানে যাই))
আপনি কি সত্যিই রূপান্তরিত মান প্রয়োজন না থাকে, তাহলে কিন্তু আপনি শুধু জানতে কিনা এটা প্রয়োজন হয় TargetType একটি দৃষ্টান্ত, তারপর is
অপারেটর আপনার বন্ধু। এই ক্ষেত্রে টার্গেটটাইপ একটি রেফারেন্স টাইপ বা মান ধরণের কিনা তা বিবেচনা করে না।
জেনেরিকগুলির সাথে জড়িত অন্যান্য ক্ষেত্রেও is
দরকারী যেখানে কার্যকর (কারণ আপনি টি জানেন না যে টি একটি রেফারেন্স টাইপ কিনা তাই আপনি এটি হিসাবে ব্যবহার করতে পারবেন না) তবে তারা তুলনামূলকভাবে অস্পষ্ট।
আমি প্রায় অবশ্যই is
আগে মান টাইপ মামলার জন্য ব্যবহার করেছি, একটি ছোট ছোট টাইপ এবং as
একসাথে ব্যবহার করার কথা চিন্তা করে না :)
সম্পাদনা: নোট করুন যে উপরোক্ত কোনওটিই পারফরম্যান্স সম্পর্কে আলোচনা করে না, মান ধরণের ক্ষেত্রে ব্যতীত, যেখানে আমি উল্লেখ করেছি যে একটি অযোগ্য মান ধরণের আনবক্সিং করা আসলে ধীর - তবে সামঞ্জস্যপূর্ণ।
নাসকিংয়ের উত্তর অনুসারে, নীচের কোডটি দেখানো অনুসারে আধুনিক জেআইটি-র সাথে-ও-কাস্ট বা হ'ল উভয়ই তত দ্রুত:
using System;
using System.Diagnostics;
using System.Linq;
class Test
{
const int Size = 30000000;
static void Main()
{
object[] values = new object[Size];
for (int i = 0; i < Size - 2; i += 3)
{
values[i] = null;
values[i + 1] = "x";
values[i + 2] = new object();
}
FindLengthWithIsAndCast(values);
FindLengthWithIsAndAs(values);
FindLengthWithAsAndNullCheck(values);
}
static void FindLengthWithIsAndCast(object[] values)
{
Stopwatch sw = Stopwatch.StartNew();
int len = 0;
foreach (object o in values)
{
if (o is string)
{
string a = (string) o;
len += a.Length;
}
}
sw.Stop();
Console.WriteLine("Is and Cast: {0} : {1}", len,
(long)sw.ElapsedMilliseconds);
}
static void FindLengthWithIsAndAs(object[] values)
{
Stopwatch sw = Stopwatch.StartNew();
int len = 0;
foreach (object o in values)
{
if (o is string)
{
string a = o as string;
len += a.Length;
}
}
sw.Stop();
Console.WriteLine("Is and As: {0} : {1}", len,
(long)sw.ElapsedMilliseconds);
}
static void FindLengthWithAsAndNullCheck(object[] values)
{
Stopwatch sw = Stopwatch.StartNew();
int len = 0;
foreach (object o in values)
{
string a = o as string;
if (a != null)
{
len += a.Length;
}
}
sw.Stop();
Console.WriteLine("As and null check: {0} : {1}", len,
(long)sw.ElapsedMilliseconds);
}
}
আমার ল্যাপটপে, এগুলি প্রায় 60 মিমিতে চালিত হয়। দুটি বিষয় লক্ষণীয়:
- তাদের মধ্যে কোনও উল্লেখযোগ্য পার্থক্য নেই। (প্রকৃতপক্ষে, এমন পরিস্থিতি রয়েছে যেখানে অস-প্লাস-নাল চেক অবশ্যই হয় ধীর উপরের কোড আসলে কারণ এটি একটি সিল বর্গ জন্য তোলে প্রকার চেক সহজ;। যদি আপনি একটি ইন্টারফেসের জন্য করছি পরীক্ষণ ভারসাম্য টিপস সামান্য হিসাবে-প্লাস-নাল-চেকের পক্ষে)
- তারা সব করছি অন্যন্ত দ্রুত। আপনি কেবলমাত্র মানগুলি পরে কিছু করতে যাচ্ছেন না যদি না এটি কেবল আপনার কোডের ক্ষেত্রে বাধা হয়ে দাঁড়াবে না ।
সুতরাং আসুন কর্মক্ষমতা সম্পর্কে চিন্তা করা উচিত না। আসুন নির্ভুলতা এবং ধারাবাহিকতা সম্পর্কে চিন্তা করুন।
আমি বজায় রাখছি যে ভেরিয়েবলগুলির সাথে কাজ করার সময় (এবং-হিসাবে) উভয়ই অনিরাপদ, কারণ এটির যে ধরণের মান উল্লেখ করা হয় তা পরীক্ষা এবং castালাইয়ের মধ্যে অন্য থ্রেডের কারণে পরিবর্তিত হতে পারে। এটি একটি খুব বিরল পরিস্থিতি হবে - তবে আমি বরং একটি কনভেনশন করব যা আমি ধারাবাহিকভাবে ব্যবহার করতে পারি।
আমি এও বজায় রেখেছি যে-পরে-নাল চেক উদ্বেগের আরও ভাল বিভাজন দেয়। আমাদের একটি বিবৃতি আছে যা রূপান্তর চেষ্টা করে এবং তারপরে একটি বিবৃতি যা ফলাফল ব্যবহার করে। হয় এবং কাস্ট বা হয় এবং হিসাবে একটি পরীক্ষা সঞ্চালিত হয় এবং তারপরে মান রূপান্তর করার জন্য আরেকটি প্রচেষ্টা attempt
এটিকে অন্য উপায়ে বলতে গেলে যে কেউ কি কখনও লিখবেন:
int value;
if (int.TryParse(text, out value))
{
value = int.Parse(text);
// Use value
}
এটি কী-কাস্ট করছে তা সাজানো - যদিও এটি সম্ভবত সস্তা পন্থায়।