Je suis juste une révision du chapitre 4 de C# en Profondeur qui traite avec des types nullables, et je vais ajouter une section sur l'utilisation de l' "que" de l'opérateur, qui permet d'écrire:
object o = ...;
int? x = o as int?;
if (x.HasValue)
{
... // Use x.Value in here
}
Je pensais que c'était vraiment bien, et qu'elle pourrait améliorer les performances sur le C# 1 équivalent, à l'aide de "est", suivi par un casting - après tout, de cette façon, nous avons seulement besoin de demander la dynamique de la vérification de type à la fois, et puis une simple vérification de valeur.
Cela ne semble pas être le cas, cependant. J'ai inclus un exemple de test d'application ci-dessous, qui, fondamentalement, résume tous les entiers dans un tableau d'objets - mais le tableau contient beaucoup de références nulles et de la chaîne de références ainsi que des entiers en boîte. L'indice de référence des mesures le code que vous auriez à utiliser en C# 1, le code en utilisant le "comme" de l'opérateur, et juste pour le plaisir d'un LINQ solution. À mon grand étonnement, le C# 1 du code est 20 fois plus rapide dans ce cas - et même le code LINQ (que je devrais devrait être plus lente, compte tenu de la itérateurs impliqués) bat le "comme" de code.
Est le .NET de la mise en œuvre de l' isinst
pour les types nullables vraiment lent? Est-il additionnelles unbox.any
que les causes du problème? Est-il une autre explication pour cela? Au moment où il se sent comme je vais avoir à inclure une mise en garde contre l'utilisation de cette performance des situations délicates...
Résultats:
Cast: 10000000 : 121
Comme: 10000000 : 2211
LINQ: 10000000 : 2143
Code:
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);
}
}