(Обновление - из комментариев) Вопрос: есть ли преимущество использования одного метода расширения над другим?
Из обсуждения, которое я веду в моей статье codeproject. в методах расширения, я не уверен, правильно ли следующее:
В настоящее время у меня есть следующий метод расширения:
public static bool In<T>(this T source, params T[] list)
{
if (null == source) throw new ArgumentNullException("source");
return list.Contains(source);
}
, который работает, как ожидалось.В комментариях было предложено изменить его так, чтобы он проверял только ссылочные типы следующим образом:
public static bool In<T>(this T source, params T[] list)
{
if (!typeof(T).IsValueType)
{
if (Equals(source, default(T))) throw new ArgumentNullException("source");
}
return list.Contains(source);
}
Опять же, это работает, как и ожидалось. Есть ли какое-либо преимущество второго метода перед первым , учитывая, что при быстром тестировании мы говорим о 0,001 второй разности для 10000 прогонов.
Выход теста (Core i3 @4 ГГц, RAID 0 ssd):
Testing performance...
Value type, original: 00:00:00.0033289
Value type, from code project: 00:00:00.0033027
Reference type, original: 00:00:00.0076951
Reference type, from code project: 00:00:00.0068459
Код теста:
Console.WriteLine("Testing performance...");
Console.WriteLine("");
const Int32 _runs = 10000;
Stopwatch sw = new Stopwatch();
Console.Write("Value type, original: ");
sw.Start();
for (Int32 i = 0; i < _runs; i++)
{
try
{
i.In(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
}
catch (Exception)
{
// do nothing
}
}
sw.Stop();
Console.WriteLine(sw.Elapsed.ToString());
sw = new Stopwatch();
Console.Write("Value type, from code project: ");
sw.Start();
for (Int32 i = 0; i < _runs; i++)
{
try
{
i.In2(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
}
catch (Exception)
{
// do nothing
}
}
sw.Stop();
Console.WriteLine(sw.Elapsed.ToString());
sw = new Stopwatch();
Console.Write("Reference type, original: ");
sw.Start();
for (Int32 i = 0; i < _runs; i++)
{
try
{
"This String".In("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10");
}
catch (Exception)
{
// do nothing
}
}
sw.Stop();
Console.WriteLine(sw.Elapsed.ToString());
sw = new Stopwatch();
Console.Write("Reference type, from code project: ");
sw.Start();
for (Int32 i = 0; i < _runs; i++)
{
try
{
"This String".In("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10");
}
catch (Exception)
{
// do nothing
}
}
sw.Stop();
Console.WriteLine(sw.Elapsed.ToString());
Console.WriteLine("");
Console.ReadLine();
public static bool In<T>(this T source, params T[] list)
{
if (source == null) throw new ArgumentNullException("source");
return list.Contains(source);
}
public static bool In2<T>(this T source, params T[] list)
{
if (!typeof(T).IsValueType)
{
if (Equals(source, default(T))) throw new ArgumentNullException("source");
}
return list.Contains(source);
}