ฉันเพิ่งแก้ไขบทที่ 4 ของ C # ในความลึกซึ่งเกี่ยวข้องกับประเภท nullable และฉันเพิ่มส่วนที่เกี่ยวกับการใช้ตัวดำเนินการ "เป็น" ซึ่งช่วยให้คุณเขียน:
object o = ...;
int? x = o as int?;
if (x.HasValue)
{
... // Use x.Value in here
}
ฉันคิดว่านี่เป็นระเบียบจริงๆและมันสามารถปรับปรุงประสิทธิภาพมากกว่า C # 1 ที่เทียบเท่าโดยใช้ "คือ" ตามด้วยนักแสดง - หลังจากทั้งหมดด้วยวิธีนี้เราเพียงแค่ต้องขอการตรวจสอบประเภทแบบไดนามิกครั้งเดียวแล้วตรวจสอบค่าง่าย ๆ .
เรื่องนี้ดูเหมือนจะไม่เป็นอย่างนั้น ฉันได้รวมแอปทดสอบตัวอย่างด้านล่างซึ่งโดยทั่วไปจะรวมจำนวนเต็มทั้งหมดภายในอาร์เรย์วัตถุ - แต่อาร์เรย์นั้นมีการอ้างอิง null และการอ้างอิงสตริงจำนวนมากรวมถึงจำนวนเต็มชนิดบรรจุกล่อง มาตรฐานวัดรหัสที่คุณต้องใช้ใน C # 1, รหัสโดยใช้ตัวดำเนินการ "เป็น" และเพียงเพื่อใช้เป็นโซลูชัน LINQ สำหรับความประหลาดใจของฉันรหัส C # 1 นั้นเร็วกว่าถึง 20 เท่าในกรณีนี้และแม้แต่รหัส LINQ (ซึ่งฉันคาดว่าจะช้าลงเนื่องจากผู้วนซ้ำที่เกี่ยวข้อง) เต้นรหัส "เป็น"
การใช้. NET isinst
สำหรับประเภท nullable เพียงช้าจริง ๆ หรือไม่ เป็นส่วนเพิ่มเติมunbox.any
ที่ทำให้เกิดปัญหาหรือไม่ มีคำอธิบายอื่นสำหรับเรื่องนี้หรือไม่? ในขณะนี้รู้สึกเหมือนว่าฉันจะต้องมีการเตือนการใช้สิ่งนี้ในสถานการณ์ที่อ่อนไหวต่อประสิทธิภาพ ...
ผล:
นำแสดงโดย: 10,000000: 121
เป็น: 10000000: 2211
LINQ: 10,000000: 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
กับประเภท nullable น่าสนใจเนื่องจากไม่สามารถใช้กับประเภทค่าอื่นได้ ที่จริงแล้วน่าแปลกใจมากขึ้น
as
พยายามโยนให้เป็นประเภทและถ้ามันล้มเหลวมันจะคืนค่าว่าง คุณไม่สามารถตั้งค่าประเภทเป็นโมฆะ