C# 在C中实现接口和应用属性之间的区别#

C# 在C中实现接口和应用属性之间的区别#,c#,interface,attributes,C#,Interface,Attributes,这可能是个愚蠢的问题但我还是要问 我在读“OOP去神秘化:Jim Keogh和Mario Giannini的自学指南”,第11章介绍了接口。本书中的例子是C++ + 我注意到C++使用ISRIALIAL化来实现一个类可序列化,你可以在其中实现,在C语言中,你只使用[SerialTime]属性来定义类。 这里的关键区别是什么?是不是有了一个接口,您必须提供一个实现,在这个实现中,编译器将为您计算出实现,就好像您赋予了某些属性一样 我猜想,对于[Serializable]属性,.Net framew

这可能是个愚蠢的问题但我还是要问

我在读“OOP去神秘化:Jim Keogh和Mario Giannini的自学指南”,第11章介绍了接口。本书中的例子是C++ +

<>我注意到C++使用ISRIALIAL化来实现一个类可序列化,你可以在其中实现,在C语言中,你只使用[SerialTime]属性来定义类。 这里的关键区别是什么?是不是有了一个接口,您必须提供一个实现,在这个实现中,编译器将为您计算出实现,就好像您赋予了某些属性一样

我猜想,对于[Serializable]属性,.Net framework使用反射从实际对象生成序列化对象

也就是说,在这种情况下,有没有可能有一个[一次性的]属性,或者使用我在框架上面的理论,你不知道如何实际处理一个对象,因此你必须自己处理


请澄清。

大多数属性仅在运行时检查。在编译时会检查一些属性(请参见下面提到的属性)。在大多数情况下,对于属性,您必须使用反射来查看对象是否拥有该属性,并决定从该属性执行什么操作

接口是编译器实现。对于接口,您可以要求参数为方法等实现它

属性:

接口:
我认为您忽略了.NET(C#)也有一个ISerializable接口的事实:

[Serializable]
class Foo : ISerializable
{
}

属性是“自定义元数据”,接口是一种语言功能。

我认为这是因为传统上某些属性被标记为可序列化或不可序列化,这意味着在类级别也有属性更有意义


与在编译时检查类型相比,在运行时检查类的属性会有轻微的性能损失。

很久以前,在遥远的银河系中。。。类元数据没有属性或编译器支持,因此开发人员尝试实现自己的。我们的祖先制定的方法之一是申报

因此,为了回答您的问题:自定义属性是标记接口的“进化”。两者都可以使用。但是请注意,如果您想要强制您的对象实现特定的方法,那么您使用的是一个简单明了的接口。这就是
IDisposable
的工作原理,它强制您实现名为
Dispose()
的方法<代码> [序列化] (可能是<代码> iSerialaby C++实例)不会强迫你实现任何东西,因为运行时将只读取该声明并执行它的任务(即序列化对象)。
请注意,C#还有一个
ISerializable
接口。。。它的目的是让您编写自定义序列化代码,然后由运行时调用。请注意,它不是标记接口,也不是
[Serializable]
属性的替代品,因为您仍然需要使用该属性标记类,以便序列化工作。

您在该属性中读取了太多内容。[Serializable]做的很少。它由BinaryFormatter类实现的二进制序列化使用。该类具有非常强大的功能,它可以创建类的实例,而无需使用该类的公共属性。它直接将值分配给标记为私有的字段,完全绕过正常的访问规则

您必须显式地授予BinaryFormatter这样做的权利,本质上承认类的对象可以被反序列化而不会出现问题。您可以通过应用[Serializable]属性来实现这一点。BinaryFormatter只是检查它是否存在。仅此而已。

属性通常提供有关类型或成员的附加元数据;关于什么是允许的(常量值等)有很大的限制,Eric Lippert提供了一些关于两者之间差异的想法,这可能会有所启发

接口还有一些其他方面:

  • 他们可以有多个成员
  • 在接口后面是一些实现(这是至关重要的)
  • 您可以使用接口进行抽象(与其说是属性)
但是,;缺点是,一旦一个类型实现了一个接口,所有子类型也通过继承实现该接口。对比度属性,可以继承,但不希望被继承

仅仅因为
Foo
是可序列化的,这并不意味着
Bar
:Foo
)必须是可序列化的;因此,能够在每个级别上定义它是很好的,尽管实际上我不认为
BinaryFormatter
应该是mots序列化代码的关键部分(不过我会咬紧牙关)

实际上,如果您检查IL,您将看到
[Serializable]
实际上并不是作为属性写入的,而是一个CLI标志(一些编译器魔法)。但这并不能改变事实


如果您只需要表示元数据(关于类型/成员的事实),那么属性是理想的。如果你需要表达一个行为/API,那么就要表达一个接口。

我认为这是一个很好的问题。事实并非如此。某些属性在编译时被检查,例如
[条件]
。但是您不能实现自己的属性在编译时进行检查(除非您使用PostSharp之类的工具)。
标记接口
对于泛型和扩展方法仍然很有用。它们允许将接口用作通用约束;某些属性当前不可能实现的功能。@Matthew:对,我认为这正是ISerializable接口存在的原因。
ISerializable
接口允许您实现自定义方法,而不是使用默认的基于反射的序列化过程。Th