С точки зрения производительности:
Атрибуты маркера будут медленнее интерфейсов маркера из-за отражения.Если вы не кэшируете рефлексию, то вызов GetCustomAttributes
все время может быть узким местом в производительности.Я тестировал это раньше, и использование интерфейсов маркеров выигрывало с точки зрения производительности даже при использовании кэшированного отражения.
Это применимо только при использовании его в часто вызываемом коде.
BenchmarkDotNet=v0.10.14, OS=Windows 10.0.16299.371 (1709/FallCreatorsUpdate/Redstone3)
Intel Core i5-2400 CPU 3.10GHz (Sandy Bridge), 1 CPU, 4 logical and 4 physical cores
Frequency=3020482 Hz, Resolution=331.0730 ns, Timer=TSC
.NET Core SDK=2.1.300-rc1-008673
[Host] : .NET Core 2.0.7 (CoreCLR 4.6.26328.01, CoreFX 4.6.26403.03), 64bit RyuJIT
Core : .NET Core 2.0.7 (CoreCLR 4.6.26328.01, CoreFX 4.6.26403.03), 64bit RyuJIT
Job=Core Runtime=Core
Method | Mean | Error | StdDev | Rank |
--------------------------- |--------------:|-----------:|-----------:|-----:|
CastIs | 0.0000 ns | 0.0000 ns | 0.0000 ns | 1 |
CastAs | 0.0039 ns | 0.0059 ns | 0.0052 ns | 2 |
CustomAttribute | 2,466.7302 ns | 18.5357 ns | 17.3383 ns | 4 |
CustomAttributeWithCaching | 25.2832 ns | 0.5055 ns | 0.4729 ns | 3 |
Это не значительная разница, хотя.
namespace BenchmarkStuff
{
[AttributeUsage(AttributeTargets.All, AllowMultiple = false)]
public class CustomAttribute : Attribute
{
}
public interface ITest
{
}
[Custom]
public class Test : ITest
{
}
[CoreJob]
[RPlotExporter, RankColumn]
public class CastVsCustomAttributes
{
private Test testObj;
private Dictionary<Type, bool> hasCustomAttr;
[GlobalSetup]
public void Setup()
{
testObj = new Test();
hasCustomAttr = new Dictionary<Type, bool>();
}
[Benchmark]
public void CastIs()
{
if (testObj is ITest)
{
}
}
[Benchmark]
public void CastAs()
{
var itest = testObj as ITest;
if (itest != null)
{
}
}
[Benchmark]
public void CustomAttribute()
{
var customAttribute = (CustomAttribute)testObj.GetType().GetCustomAttributes(typeof(CustomAttribute), false).SingleOrDefault();
if (customAttribute != null)
{
}
}
[Benchmark]
public void CustomAttributeWithCaching()
{
var type = testObj.GetType();
bool hasAttr = false;
if (!hasCustomAttr.TryGetValue(type, out hasAttr))
{
hasCustomAttr[type] = type.CustomAttributes.SingleOrDefault(attr => attr.AttributeType == typeof(CustomAttribute)) != null;
}
if (hasAttr)
{
}
}
}
public static class Program
{
public static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<CastVsCustomAttributes>();
}
}
}