用于标记类的接口或属性?

Sco*_*ott 17 c# attributes interface

我有几个类,我希望用特定的属性标记.我有两种方法.一个涉及使用属性扩展类.另一个使用空接口:

属性

public class FoodAttribute : Attribute { }

[Food]
public class Pizza { /* ... */ }

[Food]
public class Pancake { /* ... */ }

if (obj.IsDefined(typeof(FoodAttribute), false)) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

接口

public interface IFoodTag { }

public class Pizza : IFoodTag { /* ... */ }
public class Pancake : IFoodTag { /* ... */ }

if (obj is IFoodTag) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

由于使用了Reflection,我对使用这些属性犹豫不决.然而,与此同时,我对创建一个仅用作标记的空接口犹豫不决.我对它们进行了压力测试,两者之间的时间差仅为3毫秒左右,因此这里的性能并未受到影响.

ang*_*son 15

好吧,使用属性,您始终可以创建属性,使其功能不会自动传播到后代类型.

使用接口,这是不可能的.

我会选择属性.

  • 微软也推荐它,但他们在几个地方与自己的建议存在分歧。(例如 ASP.NET 中的“IRequiresSessionState”和“IReadOnlySessionState”)。 (2认同)
  • `ISerialized` 不是一个标记接口。它包含一个成员(`GetObjectData`)。实际上他们已经正确地完成了“SerializedAttribute”。 (2认同)

Jor*_*dão 7

我不得不另外说.我认为,对于您的示例,标记界面更有意义.

那是因为你很可能有一天会添加一些成员IFood.

你的设计是这样开始的:

interface IFood {}
Run Code Online (Sandbox Code Playgroud)

但是你决定在那里添加一些东西:

interface IFood {
  int Calories { get; }
}
Run Code Online (Sandbox Code Playgroud)

还有其他扩展接口的方法:

static class FoodExtensions {
  public static void Lighten(this IFood self) { 
    self.Calories /= 2;
  } 
}
Run Code Online (Sandbox Code Playgroud)


Res*_*uta 5

您可能已经自己回答了问题.属性在这里更合乎逻辑,反射不是一个有红眼的大怪物=)

顺便说一句,你能显示调用代码,你确定用接口类型标记?你不是在那里使用反射吗?

  • 不,我只是使用“is”运算符来检查给定对象是否用接口标记(请参阅“Interface”示例的最后一行)。 (2认同)