ios 枚举在 Objective-C 中定义形式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7421516/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Enum defining forms in Objective-C
提问by user500
What is the difference between
之间有什么区别
typedef enum {
...
} Name;
and
和
enum {
...
};
typedef NSUInteger Name;
? If functionality is the same, what is the second form good for? Isn't it unnecessarily messy?
? 如果功能相同,那么第二种形式有什么用?这不是不必要的混乱吗?
回答by bshirley
enum
is as old as C
, therefore a part of Objective-C
.
It is just explicit coding of an int
type. It's quite useful for debugging and most newer compilers can make optimizations based on it. (Which you should totally ignore). It's most useful in making your code more readable (to anyone else, or to yourself after you've slept).
enum
与 一样古老C
,因此是 的一部分Objective-C
。它只是一种int
类型的显式编码。它对于调试非常有用,大多数较新的编译器都可以基于它进行优化。(你应该完全忽略)。它对于使您的代码更具可读性(对其他人或您睡着后的您自己)更具可读性最有用。
typedef enum {
...
} NameType ;
would be followed by
将紧随其后
NameType name;
and that's typically the preferred style of a typedef,
这通常是 typedef 的首选样式,
your second example will nottie the typedef to the values you want to specify should only be of the given type.
您的第二个示例不会将 typedef 与您要指定的值联系起来,而该值只能是给定的类型。
Note that this does not prevent you from executing
请注意,这不会阻止您执行
name = 10244; // some non-valid value not listed in the enumeration
but some compilers might generate a warning in that case,
但在这种情况下,某些编译器可能会生成警告,
I ran across Apple's use of the following today:
我今天遇到了 Apple 对以下内容的使用:
enum {
NSFetchedResultsChangeInsert = 1,
NSFetchedResultsChangeDelete = 2,
NSFetchedResultsChangeMove = 3,
NSFetchedResultsChangeUpdate = 4
};
typedef NSUInteger NSFetchedResultsChangeType;
They do this because they reallywant the NSFetchedResultsChangeType
to be of the type they have defined as NSUInteger
. This canbe an int
but it can also be something else. And with values of 1, 2, 3, and 4, it's somewhat irrelevant to uswhat the type is. But they are coding to a different level of abstraction because they are a tools provider.
他们这样做是因为他们真的希望NSFetchedResultsChangeType
成为他们定义为 的类型NSUInteger
。这可以是一个,int
但也可以是其他东西。对于 1、2、3 和 4 的值,类型是什么对我们来说有些无关紧要。但是他们编码到不同的抽象级别,因为他们是工具提供者。
You should never look to Apple for coding style hints.If you see something that looks like it's cleaner/better way to code, it usually is. As Kevin mentioned, API stability is of paramount importance for them.
你永远不应该向 Apple 寻求编码风格的提示。如果你看到一些看起来更干净/更好的编码方式,它通常是。正如 Kevin 所提到的,API 稳定性对他们来说至关重要。
Edit (Jan 2013)If you have access to the WWDC 2012 Session Videos, you should watch Session 405 - Modern Objective-C
6:00-10:00. There is discussion a new syntax in the newer compiler that allows explicit sizing of a type and tight bonding of values to types. (borrowed from C++ 11)
编辑(2013 年 1 月)如果您可以访问 WWDC 2012 会议视频,则应在Session 405 - Modern Objective-C
6:00-10:00观看。在较新的编译器中讨论了一种新语法,它允许显式调整类型大小并将值与类型紧密结合。(从 C++ 11 借来)
enum NSFetchedResultsChangeType : NSUInteger {
NSFetchedResultsChangeInsert = 1,
NSFetchedResultsChangeDelete = 2,
NSFetchedResultsChangeMove = 3,
NSFetchedResultsChangeUpdate = 4
};
回答by Lily Ballard
The former defines a type name to refer to an enum. This is the way most enums are named in C. The latter is a bit different though, and it's prevalent in the Cocoa frameworks. There's two reasons to use the latter. The first is if your enum defines a bitfield, and you'd want it here because when you're providing a "Name" value you'll be providing a combination of the enum values. In other words, if you say something like
前者定义了一个类型名称来引用一个枚举。这是大多数枚举在 C 中的命名方式。不过后者有点不同,它在 Cocoa 框架中很普遍。使用后者有两个原因。第一个是如果您的枚举定义了一个位域,并且您希望在此处使用它,因为当您提供“名称”值时,您将提供枚举值的组合。换句话说,如果你说类似的话
[self doSomethingWithBitfield:(Enum1 | Enum2)]
you're not passing a value of Name but rather an integer that's a combination of the two.
您不是传递 Name 的值,而是传递两者组合的整数。
However, Cocoa frameworks use this idiom even for non-bitfield values, for a very good reason: API stability. According to the C standard, the underlying integral type of an enum is requires to be able to contain all values in the enum, but is otherwise chosen by the compiler. This means that adding a new enum value could change the integral type of the enum (e.g. adding -1 can make it signed, adding 6 billion can make it into a long long, etc). This is a bad thing from an API stability standpoint, because the type encoding of methods which take values of this enum could change unexpectedly and potentially break existing code and binaries. In order to prevent this, the Cocoa frameworks generally define the type as being an NSUInteger (or NSInteger if they need negative numbers), so the API and type encodings stay stable.
然而,Cocoa 框架甚至对非位域值也使用这个习惯用法,这是一个很好的理由:API 稳定性。根据 C 标准,枚举的底层整数类型要求能够包含枚举中的所有值,否则由编译器选择。这意味着添加新的枚举值可能会改变枚举的整数类型(例如,添加 -1 可以使其有符号,添加 60 亿可以使其成为 long long 等)。从 API 稳定性的角度来看,这是一件坏事,因为采用此枚举值的方法的类型编码可能会意外更改,并可能破坏现有代码和二进制文件。为了防止这种情况,Cocoa 框架通常将类型定义为 NSUInteger(如果需要负数,则为 NSInteger),因此 API 和类型编码保持稳定。