मैं केवल गहराई में C # के अध्याय 4 को संशोधित कर रहा हूं, जो अशक्त प्रकारों से संबंधित है, और मैं "के रूप में" ऑपरेटर का उपयोग करने के बारे में एक खंड जोड़ रहा हूं, जो आपको लिखने की अनुमति देता है:
object o = ...;
int? x = o as int?;
if (x.HasValue)
{
... // Use x.Value in here
}
मैंने सोचा था कि यह वास्तव में साफ-सुथरा था, और यह C # 1 के बराबर प्रदर्शन में सुधार कर सकता था, "का उपयोग करके" कास्ट द्वारा पीछा किया जाता है - आखिरकार, इस तरह से हमें केवल एक बार गतिशील प्रकार की जांच के लिए पूछना होगा, और फिर एक साधारण मूल्य की जांच ।
हालाँकि ऐसा प्रतीत नहीं होता है। मैंने नीचे एक नमूना परीक्षण ऐप शामिल किया है, जो मूल रूप से एक ऑब्जेक्ट सरणी के भीतर सभी पूर्णांकों को sums करता है - लेकिन सरणी में बहुत सारे शून्य संदर्भ और स्ट्रिंग संदर्भ के साथ-साथ बॉक्सिंग पूर्णांक शामिल हैं। बेंचमार्क उस कोड को मापता है जिसका उपयोग आपको C # 1 में करना होगा, "as" ऑपरेटर का उपयोग कर कोड, और सिर्फ एक LINK समाधान के लिए। मेरे विस्मय के लिए, C # 1 कोड इस मामले में 20 गुना तेज है - और यहां तक कि LINQ कोड (जो कि मुझे धीमी होने की उम्मीद थी, इसमें शामिल होने वाले को देखते हुए) "कोड" के रूप में धड़कता है।
क्या isinst
nullable प्रकारों के लिए .NET कार्यान्वयन वास्तव में धीमा है? क्या यह अतिरिक्त unbox.any
है जो समस्या का कारण बनता है? क्या इसके लिए कोई और स्पष्टीकरण है? फिलहाल ऐसा लगता है कि मुझे प्रदर्शन संवेदनशील स्थितियों में इसका उपयोग करने के खिलाफ चेतावनी शामिल करना है ...
परिणाम:
कास्ट: 10000000: 121
अस: 10000000: 2211
LINQ: 10000000: 2143
कोड:
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] = "";
values[i+2] = 1;
}
FindSumWithCast(values);
FindSumWithAs(values);
FindSumWithLinq(values);
}
static void FindSumWithCast(object[] values)
{
Stopwatch sw = Stopwatch.StartNew();
int sum = 0;
foreach (object o in values)
{
if (o is int)
{
int x = (int) o;
sum += x;
}
}
sw.Stop();
Console.WriteLine("Cast: {0} : {1}", sum,
(long) sw.ElapsedMilliseconds);
}
static void FindSumWithAs(object[] values)
{
Stopwatch sw = Stopwatch.StartNew();
int sum = 0;
foreach (object o in values)
{
int? x = o as int?;
if (x.HasValue)
{
sum += x.Value;
}
}
sw.Stop();
Console.WriteLine("As: {0} : {1}", sum,
(long) sw.ElapsedMilliseconds);
}
static void FindSumWithLinq(object[] values)
{
Stopwatch sw = Stopwatch.StartNew();
int sum = values.OfType<int>().Sum();
sw.Stop();
Console.WriteLine("LINQ: {0} : {1}", sum,
(long) sw.ElapsedMilliseconds);
}
}
as
अशक्त प्रकारों पर उपयोग कर सकते हैं । दिलचस्प है, क्योंकि इसका उपयोग अन्य मूल्य प्रकारों पर नहीं किया जा सकता है। दरअसल, अधिक आश्चर्य की बात है।
as
एक प्रकार के लिए कास्ट करने का प्रयास करता है और अगर यह विफल हो जाता है तो यह अशक्त हो जाता है। आप मान प्रकार को अशक्त करने के लिए सेट नहीं कर सकते हैं