How to Declare Value Types如何定义值类型
To use a type, you must first declare a symbol as an instance of that type.
在用一个类型前,你必须首先定义一个变量,作为这个类型的实例.
Value types have an implicit constructor, so declaring them instantiates the type automatically; you don't have to include the New keyword as you do with classes.
值类型有一个默认的构造器,所以这个类型会自动实例化,在你用的时候不必使用New关键字.
The constructor assigns a default value (usually null or 0) to the new instance, but you should always explicitly initialize the variable within the declaration, as shown in the following code block:
构造器分配一个默认值给这个新的实例,你也可以总是在声明的时候给它显式的初始化一个值.就像下面的代码块:
|
Keyword differences in Visual Basic and C# |
One of the cosmetic differences between Visual Basic and C# is that Visual Basic capitalizes keywords, whereas C# uses lowercase keywords. In the text of this book, keywords will always be capitalized for readability. Code samples will always include separate examples for Visual Basic and C#. ' VB Dim b As Boolean = False // C# bool b = false; |
|
Variable capitalizations in Visual Basic and C# |
C# is case-sensitive, but Visual Basic is not case-sensitive. Traditionally, variable names begin with a lowercase letter in C# and are capitalized in Visual Basic. For consistency between the languages, this book will use lowercase variable names for most Visual Basic examples. Feel free to capitalize Visual Basic variables in your own code—it will not affect how the runtime processes your code. |
Declare the variable as nullable if you want to be able to determine whether a value has not been assigned. For example, if you are storing data from a yes/no question on a form and the user did not answer the question, you should store a null value. The following code allows a Boolean variable to be true, false, or other:
通过定义一个nullable类型的变量,你可以确定一个值是否已被赋值。
举个例子,如果你想存储一个表单上问题答案的yes/no数据,有时用户没有回答这个问题,你将获取一个null值.下面的代码允许一个boolean变量被赋值为true,false或者其它.
‘ VB
Dim b As Nullable(Of Boolean) = Nothing
// C#
Nullable<bool> b = null;
// Shorthand notation, only for C#
bool? B = null;
|
NET 2.0 |
The Nullable type is new in .NET 2.0. |
Declaring a variable as nullable enables the HasValue and Value members. Use HasValue to detect whether or not a value has been set:
Nullable类型变量具有HasValue和Value两个成员.用HasValue去判断变量是否被赋值.
' VB
If b.HasValue Then Console.WriteLine("b is {0}.", b.Value) _
Else Console.WriteLine("b is not set.")
// C#
if (b.HasValue)Console.WriteLine("b is {0}.", b.Value);
else Console.WriteLine("b is not set.");
How to Create User-Defined Types如何建立自定义类型
User-defined types are also called structures or simply structs, after the language keyword used to create them. As with other value types, instances of user-defined types are stored on the stack and they contain their data directly. In most other ways, structures behave nearly identical to classes.
自定义类型也叫结构或简单结构, 用structures和structs关键字来声明它们.象其它值类型一样,自定义类型的实例和它们的数据一起存储在栈中.
在其它很多方面,结构和类非常近似.
Structures are a composite of other types that make it easier to work with related data. The simplest example of this is System.Drawing.Point, which contains X and Y integer properties that define the horizontal and vertical coordinates of a point. The Point structure simplifies working with coordinates by providing the constructor and members demonstrated here:
结构是一个包含其它类型的复合体,可以很容易的用彼此有关系的数据定义它.最简单的例子就是System.Drawing.Point,包含X和Y整数属性,用来定义一个点的横纵坐标.下面是点结构的操作示范
' VB - Requires reference to System.Drawing
' Create point
Dim p As New System.Drawing.Point(20, 30)
' Move point diagonally
p.Offset(-1, -1)
Console.WriteLine("Point X {0}, Y {1}", p.X, p.Y)
// C# - Requires reference to System.Drawing
// Create point
System.Drawing.Point p = new System.Drawing.Point(20, 30);
// Move point diagonally
p.Offset(-1, -1);
Console.WriteLine("Point X {0}, Y {1}", p.X, p.Y);
You define your own structures by using the Structure keyword in Visual Basic or the struct keyword in C#. For example, the following code creates a type that cycles through a set of integers between minimum and maximum values set by the constructor:
在VB中你通过Structure关键字定义自己的结构,或者在C#中使用Struct定义.
举个例子,下面代码建立了一个圆的类型,通过构造器设置一个范围在最大值和最小值之间的整数.
' VB
Structure Cycle
' Private fields
Dim _val, _min, _max As Integer
' Constructor
Public Sub New(ByVal min As Integer, ByVal max As Integer)
_val = min : _min = min : _max = max
End Sub
' Public members
Public Property Value() As Integer
Get
Return _val
End Get
Set(ByVal value As Integer)
' Ensure new setting is between _min and _max.
If value > _max Then _val = _min _
Else If value < _min Then _val = _max _
Else _val = value
End Set
End Property
Public Overrides Function ToString() As String
Return Value.ToString
End Function
Public Function ToInteger() As Integer
Return Value
End Function
' Operators (new in 2.0)
Public Shared Operator +(ByVal arg1 As Cycle, _
ByVal arg2 As Integer) As Cycle
arg1.Value += arg2
Return arg1
End Operator
Public Shared Operator -(ByVal arg1 As Cycle, _
ByVal arg2 As Integer) As Cycle
arg1.Value -= arg2
Return arg1
End Operator
End Structure
// C#
struct Cycle
{
// Private fields
int _val, _min, _max;
// Constructor
public Cycle(int min, int max)
{
_val = min;
_min = min;
_max = max;
}
public int Value
{
get { return _val; }
set
{
if (value > _max)
_val = _min;
else
{
if (value < _min)
_val = _max;
else
_val = value;
}
}
}
public override string ToString()
{
return Value.ToString();
}
public int ToInteger()
{
return Value;
}
// Operators (new in .NET 2.0)
public static Cycle operator +(Cycle arg1, int arg2)
{
arg1.Value += arg2;
return arg1;
}
public static Cycle operator -(Cycle arg1, int arg2)
{
arg1.Value -= arg2;
return arg1;
}
}
|
.NET 2.0 |
The Operator keyword is new in .NET 2.0. |
|
|
只有.net2.0提供Operator关键字 |
You can use this structure to represent items that repeat over a fixed range, such as degrees of rotation or quarters of a football game, as shown here:
你可以用结构去描述象弧度或者一个足球游戏中的位置这样,反复出现在一个固定范围内的对象,象下面的代码.
' VB
Dim degrees As New Cycle(0, 359), quarters As New Cycle(1, 4)
For i As Integer = 0 To 8
degrees += 90 : quarters += 1
Console.WriteLine("degrees = {0}, quarters = {1}", degrees, quarters)
Next
// C#
Cycle degrees = new Cycle(0, 359);
Cycle quarters = new Cycle(1, 4);
for (int i = 0; i <= 8; i++)
{
degrees += 90; quarters += 1;
Console.WriteLine("degrees = {0}, quarters = {1}", degrees, quarters);
}
The Cycle sample can be easily converted to and from a value type to a reference type by changing the Structure/struct keywords to Class. If you make that change, instances of the Cycle class would be allocated on the managed heap rather than as 12 bytes on the stack (4 bytes for each private integer field) and assignment between two variables results in both variables pointing to the same instance.
通过将struct关键字改变为class关键字,可以很容易的将这个圆的例子从一个值类型转变为引用类型.如果你进行了这种改变,圆类的实例将被分配给堆,而对于同样使用12bytes (每个私有整数占4bytes)来说,在管理上使用堆就胜于使用栈,并且分配给两个变量的值都指向同一个实例.
(注: Heap是堆,stack是栈。Stack的空间由操作系统自动分配/释放,Heap上的空间手动分配/释放。Stack空间有限,Heap是很大的自由存储区)
While the functionality is similar, structures are usually more efficient than classes. You should define a structure, rather than a class, if the type will perform better as a value type than a reference type.
当实现的功能类似时,结构通常比类更有效率.你定义一个结构比定义一个类强,如果要使用一个类型的话,使用值类型要比使用引用类型更好.
Specifically, structure types should meet all of these criteria:
结构类型特别适合下面这些标准:
· Logically represents a single value逻辑上表达一个单一的值情况
· Has an instance size less than 16 bytes有一个小于16bytes的实例的情况
· Will not be changed after creation在建立后将不会被改变的情况
· Will not be cast to a reference type不会被转换为一个引用类型情况
How to Create Enumerations如何建立枚举类型
Enumerations are related symbols that have fixed values. Use enumerations to provide a list of choices for developers using your class. For example, the following enumeration contains a set of titles:
枚举是固定值之间关系的特征(符号),在你的类中使用枚举来为开发人员提供一个选项列表.举个例子,下面枚举类型包含了一个标题集.
' VB
Enum Titles As Integer
Mr
Ms
Mrs
Dr
End Enum
// C#
enum Titles : int { Mr, Ms, Mrs, Dr };
If you create an instance of the Titles type, Visual Studio displays a list of the available values when you assign a value to the variable. Although the value of the variable is an integer, it is easy to output the name of the symbol rather than its value, as shown here:
如果你建立一个Titles类型的实例,当你给这个变量赋值时VS会显示Titles类型中成员的列表供你选择.尽管Titles变量的值是个整数,但使用它比使用它的值更方便.就象下面:
' VB
Dim t As Titles = Titles.Dr
Console.WriteLine("{0}.", t) ' Displays "Dr."
// C#
Titles t = Titles.Dr;
Console.WriteLine("{0}.", t); // Displays "Dr."
The purpose of enumerations is to simplify coding and improve code readability by enabling you to use meaningful symbols instead of simple numeric values. Use enumerations when developers consuming your types must choose from a limited set of choices for a value.
通过允许你使用枚举类型中的预定义成员来代替简单数值,枚举类型可以起到简化编码和改善代码可读性的目的.当开发人员希望要求自定义类型必须从一个有限的选择集中选择的时候,请使用枚举类型。
Lab: Declaring and Using Value Types实验:声明和使用值类型
The following exercises demonstrate how to create and use a structure and how to create an enumeration. If you encounter a problem completing an exercise, the completed projects are available on the companion CD in the Code folder.
下面的练习示范如何建立并使用一个结构和如何建立一个枚举类型.如果你在完成习题是遇到了麻烦,可以利用配套CD光盘code目录中提供的已经完成的项目.
Exercise 1: Create a Structure ;练习1:建立一个结构
|
In this exercise, you will create a simple structure with several public members.
在这个练习中,你将建立一个包含几个公共成员的简单结构
1. Using Visual Studio, create a ne w console application project. Name the project CreateStruct.
打开VS,建立一个新的控制台应用程序项目.项目名称为CreateStruct
2. Create a new structure named Person, as the following code demonstrates:
建立一个新的命名为Person的结构,象下面的代码示例:
3. ' VB
4. Structure Person
5. End Structure
6.
7. // C#
8. struct Person
9. {
10. }
11.Within the Person structure, define three public members:
在Person结构中定义三个公共成员
o firstName (a String)
o lastName (a String)
o age (an Integer)
The following code demonstrates this:下面是代码示例
' VB
Public firstName As String
Public lastName As String
Public age As Integer
// C#
public string firstName;
public string lastName;
public int age;
12.Create a constructor that defines all three member variables, as the following code demonstrates:
建立一个构造器,用来定义所有三个成员变量
13. ' VB
14. Public Sub New(ByVal _firstName As String, ByVal _lastName As String, ByVal _age As
15. Integer)
16. firstName = _firstName
17. lastName = _lastName
18. age = _age
19. End Sub
20.
21. // C#
22. public Person(string _firstName, string _lastName, int _age)
23. {
24. firstName = _firstName;
25. lastName = _lastName;
26. age = _age;
27. }
28.Override the ToString method to display the person's first name, last name, and age. The following code demonstrates this:
覆盖ToString()方法用来显示这个person的三个成员变量
29. ' VB
30. Public Overloads Overrides Function ToString() As String
31. Return firstName + " " + lastName + ", age " + age.ToString
32. End Function
33.
34. // C#
35. public override string ToString()
36. {
37. return firstName + " " + lastName + ", age " + age;
38. }
39.Within the Main method of the console application, write code to create an instance of the structure and pass the instance to the Console.WriteLine method, as the following code demonstrates:
在Main方法中编写代码,建立一个这个结构的实例,并且将这个实例传递给Console.WriteLine方法
40. ' VB
41. Dim p As Person = New Person("Tony", "Allen", 32)
42. Console.WriteLine(p)
43.
44. // C#
45. Person p = new Person("Tony", "Allen", 32);
46. Console.WriteLine(p);
47.Run the console application to verify that it works correctly.
|
|
Exercise 2: Add an Enumeration to a Structure 练习2:给结构增加一个枚举类型
|
In this exercise, you will extend the structure you created in Exercise 1 by adding an enumeration.
在这个练习中,你将通过增加一个枚举练习来扩展你在练习1中建立的结构.
1. Open the project you created in Exercise 1.
打开你在练习1时建立的项目
2. Declare a new enumeration in the Person structure. Name the enumeration Genders, and specify two possible values: Male and Female. The following code sample demonstrates this:
在Person结构中声明一个名字为Genders的枚举类型. 并指定两个可能的值Male和female.
3. ' VB
4. Enum Genders
5. Male
6. Female
7. End Enum
8.
9. // C#
10. public enum Genders : int { Male, Female };
11.Add a public member of type Genders, and modify the Person constructor to accept an instance of Gender. The following code demonstrates this:
增加一个Genders类型公共成员,并且修改Person构造器,让它可以接受一个Genders的实例.
12. ' VB
13. Public firstName As String
14. Public lastName As String
15. Public age As Integer
16. Public gender As Genders
17.
18. Public Sub New(ByVal _firstName As String, ByVal _lastName As String, _
19. ByVal _age As Integer, ByVal _gender As Genders)
20. firstName = _firstName
21. lastName = _lastName
22. age = _age
23. gender = _gender
24. End Sub
25.
26. // C#
27. public string firstName;
28. public string lastName;
29. public int age;
30. public Genders gender;
31.
32. public Person(string _firstName, string _lastName, int _age, Genders _gender)
33. {
34. firstName = _firstName;
35. lastName = _lastName;
36. age = _age;
37. gender = _gender;
38. }
39.
40.Modify the Person.ToString method to also display the gender, as the following code sample demonstrates:
修改person.ToString()方法,让它同时可以显示这个gender,
41. ' VB
42. Public Overloads Overrides Function ToString() As String
43. Return firstName + " " + lastName + " (" + gender.ToString() + "), age " +
44. age.ToString
45. End Function
46.
47. // C#
48. public override string ToString()
49. {
50. return firstName + " " + lastName + " (" + gender + "), age " + age;
51. }
52.Modify your Main code to properly construct an instance of the Person class, as the following code sample demonstrates:
修改你的Main方法代码来构造一个person类的实例
53. ' VB
54. Sub Main()
55. Dim p As Person = New Person("Tony", "Allen", 32, Person.Genders.Male)
56. Console.WriteLine(p)
57. End Sub
58.
59. // C#
60. static void Main(string[] args)
61. {
62. Person p = new Person("Tony", "Allen", 32, Person.Genders.Male);
63. Console.WriteLine(p.ToString());
64. }
65.Run the console application to verify that it works correctly.
运行这个程序来验证程序的正确性.
|
|
Lesson Summary课程摘要
· The .NET Framework includes a large number of built-in types that you can use directly or use to build your own custom types.
· .net框架包含了大量的、可直接使用的或者用来建立自定义类型的默认类型
· Value types directly contain their data, offering excellent performance. However, value types are limited to types that store very small pieces of data. In the .NET Framework, all value types are 16 bytes or shorter.
· 值类型直接包含它们的数据,提供非常好的性能.可是,值类型是有限的,它仅能存储微小数据块.在.net框架中所有值类型都是16bytes或更小.
· You can create user-defined types that store multiple values and methods. In object-oriented development environments, a large portion of your application logic will be stored in user-defined types.
· 你可以建立自定义类型,用来存储各种值和方法.在面向对象开发环境中,应用程序的大部分都会被存储在自定义类型中.
· Enumerations improve code readability by providing symbols for a set of values.
· 枚举类型通过预定义好的值的集合来改善代码可读性
Lesson Review复习
You can use the following questions to test your knowledge of the information in Lesson 1, "Using Value Types." The questions are also available on the companion CD if you prefer to review them in electronic form.
你可以使用下面的问题来测试你在练习1中学到的知识,如果你更喜欢通过电子的方式复习它们,可以利用CD中的电子版.
|
Answers |
Answers to these questions and explanations of why each answer choice is right or wrong are located in the "Answers" section at the end of the book. |
Answers
Correct Answers: A, C, and D A. Correct: Decimal is a value type. B. Incorrect: String is a reference type. C. Correct: System.Drawing.Point is a value type. D. Correct: Integer is a value type. | |
Correct Answer: B A. Incorrect: First, value types must be initialized before being passed to a procedure unless they are specifically declared as nullable. Second, passing a null value would not affect the behavior of a value type. 首先,除非值类型已经被显式的定义为nullable类型,否则值类型必须在传入程序前被初始化,第二,给值类型赋null值,并不影响它的使用。 B. Correct: Procedures work with a copy of variables when you pass a value type. Therefore, any modifications that were made to the copy would not affect the original value. 程序使用的只是传入值类型的一个拷贝。因此,如何改变都不会影响原始数据。 C. Incorrect: The variable might have been redeclared, but it would not affect the value of the variable. 变量可能会被重定义,但是它不会影响传入的值类型 D. Incorrect: If the variable had been a reference, the original value would have been modified. 如果是引用类型,则原始值会被改变。 | |
Correct Answer: B A. Incorrect: The Visual Basic sample uses angle brackets rather than parentheses. The C# sample uses parentheses rather than angle brackets. Vb用的是圆括号,c#用的是尖括号。 B. Correct: This is the proper way to declare and assign a nullable integer. In C#, you could also use the following: int? i = null; 这是正确的定义和赋值方式。在C#中,也会这样使用:int?i=null; C. Incorrect: You must use the Nullable generic to declare an integer as nullable. By default, integers are not nullable. 你必须用nullable定义。整数默认不是nullable类型。 D. Incorrect: This is not the correct syntax for using the Nullable generic. 错误的语法 | |
Correct Answer: D A. Incorrect: You could create a reference class; however, it could be modified when passed to a procedure. 你可以定义一个引用类型,可是它在传入程序中后会被修改。 B. Incorrect: You cannot create a reference structure. 不可用定义一个引用结构。 C. Incorrect: You could create a value class; however, structures tend to be more efficient. 可以建立一个值类,可是结构会更有效率。 D. Correct: Value structures are typically the most efficient. 值结构是最有效率的代表。
| |
|
|