Enums and Structs in C#(C#里的枚举和结构) (from codeproject)
原作者:Nishant S
Introduction
Just about everything is a heap object when you are using C#. Only elementary native types like int are treated as value types. But there are two value types in C# that are pretty much more useful that first glances would tell you. They are the enum and struct types. Very few tutorials even cover these topics, but they have their own uses. And both of them are a lot more efficient than classes and you can use them in place of classes when they meet your requirements to improve performance.
介紹
?
當(dāng)你使用C#時(shí),幾乎所有東西都是儲(chǔ)存在堆上的對(duì)象。只有基本的原生類型比如說 int 作為值類型創(chuàng)建。但有兩種值類型當(dāng)你第一眼看到時(shí)就會(huì)覺得更加有用。它們是enum 跟struct類型。幾乎沒有指導(dǎo)書有這兩個(gè)類型的主題,但它們自有用處。而且它們兩個(gè)都有比類更加有效率的地方。當(dāng)你有需要改善你的程序的時(shí)候,你可以用它們兩個(gè)來代替類。
?
Enums
Enums are basically a set of named constants. They are declared in C# using the enum keyword. Every enum type automatically derives from System.Enum and thus we can use System.Enum methods on our Enums. Enums are value types and are created on the stack and not on the heap. You don't have to use new to create an enum type. Declaring an enum is a little like setting the members of an array as shown below.
?
枚舉
?
Enums(枚舉)基本上是一些取了名的常量的集合。它們?cè)?/span>C# 中用 enum 關(guān)鍵字聲明。所有的枚舉類型都自動(dòng)(隱含)得從System.Enum繼承,所以我們可以在我們自己的枚舉類型中使用System.Enum中的方法。枚舉是值類型,它被創(chuàng)建在堆棧上而不是堆上。你不必使用new操作符來創(chuàng)建一個(gè)枚舉類型。聲明一個(gè)枚舉有點(diǎn)像為一個(gè)數(shù)組設(shè)置數(shù)組成員,如下所示:
?
?
You can pass enums to member functions just as if they were normal objects. And you can perform arithmetic on enums too. For example we can write two functions, one to increment our? enum and the other to decrement our enum.
?
你可以把枚舉傳遞給成員函數(shù)就好像它們是普通的對(duì)象。你也可以在枚舉上進(jìn)行算術(shù)運(yùn)算。比如說我們寫了兩個(gè)函數(shù),一個(gè)用來使我們的枚舉自增(increment),而另一個(gè)用來使它自減(decrement)。
{
????if(r?==?Rating.Excellent)
????????return?r;
????else
????????return?r+1;
}
Rating?DecrementRating(Rating?r)
{
????if(r?==?Rating.Poor)
????????return?r;
????else
????????return?r-1;
}
兩個(gè)函數(shù)都把Rating對(duì)象作為參數(shù),同時(shí)返回一個(gè)Rating對(duì)象值?,F(xiàn)在我們就可以從任何地方簡(jiǎn)單地調(diào)用這些函數(shù)了
。
????r1?<?Rating.Excellent?;?
????r1?=?IncrementRating(r1))
{???????????
????Console.WriteLine(r1);
}
Console.WriteLine();
for?(Rating?r2?=?Rating.Excellent;?
????r2?>?Rating.Poor;?
????r2?=?DecrementRating(r2))
{
????Console.WriteLine(r2);??????????
}
這是一個(gè)示例代碼小片段,用來展示我們?nèi)绾握{(diào)在我們的Enum對(duì)象里用System.Enum中的方法。我們可以使用GetNames方法來得到一個(gè)數(shù)組,這個(gè)數(shù)組包含定義在枚舉中的常量成員。
Where to use enums
Quite often we have situations where a class method takes as an argument a custom option. Let's say we have some kind of file access class and there is a file open method that has a parameter that might be one of read-mode, write-mode, read-write-mode, create-mode and append-mode. Now you might think of adding five static member fields to your class for these modes. Wrong approach! Declare and use an enumeration which is a whole lot more efficient and is better programming practice in my opinion.
哪里該使用枚舉
我們經(jīng)常遇到這種情況,一個(gè)類的方法把參數(shù)作為自選項(xiàng)。比如說我們有某個(gè)文件存取類,其中有一個(gè)打開文件的方法,它有一個(gè)參數(shù),可能是只讀模式,只寫模式,讀寫模式,創(chuàng)建模式,追加模式中的一種。這時(shí)你可能想為這些模式加5個(gè)靜態(tài)字段作為類成員。錯(cuò)了!在我看來,聲明和使用枚舉效率高得多的了,是一個(gè)更好的編程習(xí)慣。
(PS:我把argument跟parameter都翻譯成參數(shù),但是不知道它們的區(qū)別,希望高手指點(diǎn))
????(經(jīng)過Ninputer指出,應(yīng)該是argument是“實(shí)參” ,parameter是“形參” )
Structs
In C++ a struct is just about the same as a class for all purposes except in the default access modifier for methods. In C# a struct are a pale puny version of a class. I am not sure why this was done so, but perhaps they decided to have a clear distinction between structs and classes. Here are some of the drastic areas where classes and structs differ in functionality.
- structs are stack objects and however much you try you cannot create them on the heap
- structs cannot inherit from other structs though they can derive from interfaces
- You cannot declare a default constructor for a struct, your constructors must have parameters
- The constructor is called only if you create your struct using new, if you simply declare the struct just as in? declaring a native type like int, you must explicitly set each member's value before you can use the struct
結(jié)構(gòu)
在C++里,除方法的默認(rèn)訪問修飾符,任何情況結(jié)構(gòu)都跟類是一樣的。(我沒學(xué)過C++,就不知道這個(gè)是什么意思了)。在C#里,結(jié)構(gòu)可以算是一種功能較弱的類。我不確定為什么會(huì)被這樣處理,可能他們決定讓結(jié)構(gòu)跟類有一個(gè)明確的區(qū)別。下面是一些類跟結(jié)構(gòu)在功能上明顯不同的地方:
- 無論你多想把結(jié)構(gòu)創(chuàng)建在堆上,結(jié)構(gòu)都是存放在堆棧上的對(duì)象
- 一個(gè)結(jié)構(gòu)無法從另一個(gè)結(jié)構(gòu)繼承,但它們可以繼承接口(實(shí)現(xiàn)接口)
- 你不能為結(jié)構(gòu)聲明一個(gè)默認(rèn)構(gòu)造器 ,你的構(gòu)造器必須有參數(shù)
- 只有在你創(chuàng)建結(jié)構(gòu)的時(shí)候使用new操作符,構(gòu)造器才會(huì)被調(diào)用。如果你只是簡(jiǎn)單的聲明結(jié)構(gòu)就像聲明原生類型int那樣,你就必須在使用這個(gè)結(jié)構(gòu)以前,顯式地為每個(gè)結(jié)構(gòu)的成員賦值。
?
struct?Student?:?IGrade{???
????public?int?maths;
????public?int?english;
????public?int?csharp;
????//public?member?function
????public?int?GetTot()
????{
????????return?maths+english+csharp;
????}
????//We?have?a?constructor?that?takes?an?int?as?argument
????public?Student(int?y)
????{
????????maths?=?english?=?csharp?=?y;
????}
????//This?method?is?implemented?because?we?derive
????//from?the?IGrade?interface
????public?string?GetGrade()
????{
????????if(GetTot()?>?240?)
????????????return?"Brilliant";
????????if(GetTot()?>?140?)
????????????return?"Passed";
????????return?"Failed";
????}
}
interface?IGrade
{
????string?GetGrade();
}
?
Well, now let's take a look at how we can use our struct.好了,現(xiàn)在讓我們來看看怎么使用我們的結(jié)構(gòu)。
?
Here the default constructor gets called. This is automatically implemented for us and we cannot have our own default parameter-less constructor. The default parameter-less constructor simply initializes all values to their zero-equivalents. This is why we get a 0 as the total.
這里默認(rèn)構(gòu)造器被調(diào)用了。這是自動(dòng)執(zhí)行的,我們不能有自己的默認(rèn)無參構(gòu)造器(default parameter-less constructor我不知道這樣翻譯對(duì)不對(duì),但我覺得應(yīng)該是這個(gè)意思)。默認(rèn)無參構(gòu)造器只是簡(jiǎn)單地把所有值初始化為它們的0等價(jià)值(zero-equivalents,雖然翻譯的不倫不類的,但我想大家應(yīng)該知道是什么意思,哈),這就是為什么我們的total變量得到了0值。
?
Because we haven't used new, the constructor does not get called. Of all the silly features this one must win the annual contest by a long way. I see no sane reason why this must be so. Anyway you have to initialize all the member fields. If you comment out the line that does the initialization you will get a compiler error :- Use of unassigned local variable 's2'
因?yàn)槲覀儧]有使用new操作符,構(gòu)造器就沒有被調(diào)用。在所有愚蠢的特性中,這一個(gè)定會(huì)在年度討論會(huì)中壓倒性勝出。我沒有發(fā)現(xiàn)任何健全的理由為什么這樣做??傊惚仨氉约撼跏蓟谐蓡T字段。如果你把那行(初始化所有成員字段的那行)注釋掉,你會(huì)得到一個(gè)編譯器錯(cuò)誤:
error CS0165: 使用了未賦值的局部變量“s2”(這是我的編譯器顯示的,哈)
?
This time we use our custom constructor that takes an int as argument.
這次我們的自定義構(gòu)造器把一個(gè)int作為參數(shù)了。
When to use structs
Because structs are value types they would be easier to handle and more efficient that classes. When you find that you are using a class mostly for storing a set of values, you must replace those classes with structs. When you declare arrays of structs because they are created on the heap, efficiency again improves. Because if they were classes each class object would need to have memory allocated on the heap and their references would be stored. In fact lots of classes within the .NET framework are actually structs. For example System.Drawing.Point is actually a struct and not a class.
什么時(shí)候該使用結(jié)構(gòu)
因?yàn)榻Y(jié)構(gòu)是值類型,它們比類更加易于操作,更加有效率。當(dāng)你發(fā)現(xiàn)你正在使用一個(gè)類主要用于儲(chǔ)存一些值的集合,你就必須用結(jié)構(gòu)代替類。當(dāng)你聲明一個(gè)結(jié)構(gòu)數(shù)組,由于它們被創(chuàng)建在堆上,效率又一次被提高了。如果它們是類,則每一個(gè)類的對(duì)象都要在堆上分配空間,它們的對(duì)象的引用就被儲(chǔ)存了(我覺得引用應(yīng)該是在堆棧上)。事實(shí)上很多.NET框架里的類實(shí)際上是結(jié)構(gòu)。比如說System.Drawing.Point實(shí)際上是一個(gè)結(jié)構(gòu)而不是一個(gè)類。
?原文及源代碼請(qǐng)參見
http://www.codeproject.com/csharp/csenums01.asp
總結(jié)
以上是生活随笔為你收集整理的Enums and Structs in C#(C#里的枚举和结构) (from codeproject)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Flex 常见问题解答(from MM)
- 下一篇: c# char unsigned_dll