Tôi chỉ sửa đổi chương 4 của C # in Depth liên quan đến các loại nullable và tôi đang thêm một phần về cách sử dụng toán tử "as", cho phép bạn viết:
object o = ...;
int? x = o as int?;
if (x.HasValue)
{
... // Use x.Value in here
}
Tôi nghĩ rằng điều này thực sự gọn gàng và nó có thể cải thiện hiệu suất so với tương đương C # 1, sử dụng "is" theo sau là một diễn viên - sau tất cả, cách này chúng ta chỉ cần yêu cầu kiểm tra loại động một lần, và sau đó kiểm tra giá trị đơn giản .
Điều này dường như không phải là trường hợp, tuy nhiên. Tôi đã bao gồm một ứng dụng thử nghiệm mẫu bên dưới, về cơ bản tổng hợp tất cả các số nguyên trong một mảng đối tượng - nhưng mảng chứa rất nhiều tham chiếu null và tham chiếu chuỗi cũng như các số nguyên được đóng hộp. Điểm chuẩn đo lường mã bạn phải sử dụng trong C # 1, mã sử dụng toán tử "as" và chỉ để khởi động giải pháp LINQ. Trước sự ngạc nhiên của tôi, mã C # 1 nhanh hơn 20 lần trong trường hợp này - và thậm chí mã LINQ (mà tôi dự kiến sẽ chậm hơn, do các trình lặp có liên quan) đánh bại mã "dưới dạng".
Là triển khai .NET isinst
cho các loại nullable thực sự chậm? Có phải nó là bổ sung unbox.any
gây ra vấn đề? Có một lời giải thích khác cho điều này? Hiện tại tôi cảm thấy mình sẽ phải đưa ra một cảnh báo về việc sử dụng điều này trong các tình huống nhạy cảm về hiệu suất ...
Các kết quả:
Diễn viên: 10000000: 121
Như: 10000000: 2211
LINQ: 10000000: 2143
Mã số:
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
trên các loại nullable. Thật thú vị, vì nó không thể được sử dụng trên các loại giá trị khác. Thật ra, đáng ngạc nhiên hơn.
as
cố gắng chuyển sang một loại và nếu thất bại thì nó trả về null. Bạn không thể đặt loại giá trị thành null