Chapter 1: 使用引用类型
这是系列文章,是读"MS Press - MCTS Self-Paced Training Kit"的笔记,并把主要部分翻译成中文。
作者地址:http://www.cnblogs.com/nevernet (转载请保留)
Lesson 2: 使用引用类型
.NET Framework里面大部分类型都是引用类型,它们提供了极好的性能。
这节课之后,你将能够做:
解释值类型和引用类型之间的不同之处.
描述值类型和引用类型在传递值有何具体不同.
列出内建的引用类型.
说明你什么时候该用StringBuilder类型.
创建数组并排序.
打开、读取、写入和关闭文件.
当异常发生时做出检测,并做出相应的响应.
估计本课时间: 40 minutes
什么是引用类型?
Best Practices—Garbage collection |
Garbage collection occurs only when needed or when triggered by a call to GC.Collect. Automatic garbage collection is optimized for applications where most instances are short-lived, except for those allocated at the beginning of the application. Following that design pattern will result in the best performance. |
比较引用类型和值类型的行为
因为引用类型表示的是数据的地址,而不是数据本身,所以当把一个引用变量赋值给另外一个变量时,并没有复制数据,相反,仅仅是复制了引用(译者注:仅仅是复制了这个数据的地址)实际上,他们指向的数据都是一样的.
考虑下面的代码片段:
' VBStructure Numbers Public val As Integer Public Sub New(ByVal _val As Integer) val = _val End Sub Public Overloads Overrides Function ToString() As String Return val.ToString End FunctionEnd Structure // C#struct Numbers{ public int val; public Numbers(int _val) { val = _val; } public override string ToString() { return val.ToString(); }}
现在再考虑如下代码:
' VBDim n1 As Numbers = New Numbers(0)Dim n2 As Numbers = n1n1.val += 1n2.val += 2Console.WriteLine("n1 = {0}, n2 = {1}", n1, n2) // C#Numbers n1 = new Numbers(0);Numbers n2 = n1;n1.val += 1;n2.val += 2;Console.WriteLine("n1 = {0}, n2 = {1}", n1, n2);
结果将显示 "n1 = 1, n2 = 2" ,因为它们是值类型, 但是,当你更改一个引用类型时, 将会更改所有该引用类型的副本(copies).
内建引用类型
在 .NET Framework里面,有大约2500种内建引用类型. Table 1-3 列出了经常使用的类型
Type |
Use for |
---|---|
System.Object |
The Object type is the most general type in the Framework. You can convert any type to System.Object, and you can rely on any type having ToString, GetType, and Equals members inherited from this type. |
System.String |
Text data. |
System.Text.StringBuilder |
Dynamic text data. |
System.Array |
Arrays of data. This is the base class for all arrays. Array declarations use language-specific array syntax. |
System.IO.Stream |
Buffer for file, device, and network I/O. This is an abstract base class; task-specific classes are derived from Stream. |
System.Exception |
Handling system and application-defined exceptions. Task-specific exceptions inherit from this type. |
Strings and String Builders
这个两个类型不仅仅只是一个装数据的容器,也提供一些方法来操作数据,如下:
' VBDim s As String = "this is some text to search"s = s.Replace("search", "replace")Console.WriteLine(s) // C#string s = "this is some text to search";s = s.Replace("search", "replace");Console.WriteLine(s);
在 .NET里面,System.String类型的变量是不可变的. 在运行的时候,如果赋值给一个string类型的变量,将复制一个新的值(与值类型的行为相同)
' VBDim s As String s = "wombat" ' "wombat"s += " kangaroo" ' "wombat kangaroo"s += " wallaby" ' "wombat kangaroo wallaby"s += " koala" ' "wombat kangaroo wallaby koala"Console.WriteLine(s) // C#string s; s = "wombat"; // "wombat"s += " kangaroo"; // "wombat kangaroo"s += " wallaby"; // "wombat kangaroo wallaby"s += " koala"; // "wombat kangaroo wallaby koala"Console.WriteLine(s);
只有最后一个字符串有引用; 其它三个将被垃圾回收机制回收. 减少这样的操作(因为这种操作将多次调用垃圾回收机制),将有助于提高性能. 其它办法如下:
用String类来合并、加入、格式化等方法把多个items变成一个.
用 StringBuilder类 创建动态字符串.
StringBuilder 方案提供了很大的灵活性.下面是使用StringBuilder的演示:
' VBDim sb As New System.Text.StringBuilder(30)sb.Append("wombat") ' Build string.sb.Append(" kangaroo")sb.Append(" wallaby")sb.Append(" koala")Dim s as String = sb.ToString ' Copy result to string.Console.WriteLine(s) // C#System.Text.StringBuilder sb = new System.Text.StringBuilder(30);sb.Append("wombat"); // Build string.sb.Append(" kangaroo");sb.Append(" wallaby");sb.Append(" koala");string s = sb.ToString(); // Copy result to string.Console.WriteLine(s);
String class 来自 System.Object 运算符重载. Table 1-4 lists the operators the String class overrides.
Operator |
Visual Basic |
C# |
Action on System.String |
---|---|---|---|
Addition |
+ or & |
+ |
Joins two strings to create a new string. |
Equality |
= |
= = |
Returns True if two strings have the same contents; False if they are different. |
Inequality |
<> |
!= |
The inverse of the equality operator. |
Assignment |
= |
= |
Copies the contents of one string into a new one. This causes strings to behave like value types, even though they are implemented as reference types. |
如何创建数组并排序?
Arrays 使用 圆括号 (in Visual Basic) 或者方括号 (in C#) 来定义的:
' VB' Declare and initialize an array.Dim ar() As Integer = {3, 1, 2} ' Call a shared/static array method.Array.Sort(ar) ' Display the result.Console.WriteLine("{0}, {1}, {2}", ar(0), ar(1), ar(2)) // C#// Declare and initialize an array.int[] ar = { 3, 1, 2 }; // Call a shared/static array method.Array.Sort(ar); // Display the result.Console.WriteLine("{0}, {1}, {2}", ar[0], ar[1], ar[2]);
如何使用 Streams?
Streams are another very common type because they are the means for reading from and writing to the disk and communicating across the network. The System.IO.Stream type is the base type for all task-specific stream types. Table 1-5 shows some of the most commonly used stream types. 另外, network streams 可以在 System.Network.Sockets 命名空间下找到, encrypted streams 可以在System.Security.Cryptography 命名空间下找到。
System.IO Type |
Use to |
---|---|
FileStream |
Create a base stream used to write to or read from a file |
MemoryStream |
Create a base stream used to write to or read from memory |
StreamReader |
Read data from the stream |
StreamWriter |
Write data to the stream |
最简单的 stream 类是StreamReader和StreamWriter, 它们支持你对文本文件的读写. You can pass a filename as part of the constructor, enabling you to open a file with a single line of code. After you have processed a file, call the Close method so that the file does not remain locked. The following code, which requires the System.IO namespace, 下面代码演示如何读写文本文件:
' VB' Create and write to a text fileDim sw As StreamWriter = New StreamWriter("text.txt")sw.WriteLine("Hello, World!")sw.Close ' Read and display a text fileDim sr As StreamReader = New StreamReader("text.txt")Console.WriteLine(sr.ReadToEnd)sr.Close // C#// Create and write to a text fileStreamWriter sw = new StreamWriter("text.txt");sw.WriteLine("Hello, World!");sw.Close(); // Read and display a text fileStreamReader sr = new StreamReader("text.txt");Console.WriteLine(sr.ReadToEnd());sr.Close();
More Info—Streams |
更多关于streams的信息, refer to Chapter 2, "Input/Output (I/O)." |
如何抛出和捕捉 Exceptions
Exceptions are unexpected events that interrupt normal execution of an assembly. For example, if your assembly is reading a large text file from a removable disk and the user removes the disk, the runtime will throw an exception. This makes sense because there is no way your assembly could continue running.
Exceptions should never cause your assembly to fail completely.相反 , 你应该计划异常何时发生, 捕捉它们, 并对这个事件做出回应. In the preceding example, you could notify the user that the file was not available, and then await further instructions from the user. The following simplified code, which requires the System.IO namespace, demonstrates this:
' VBTry Dim sr As StreamReader = New StreamReader("C:\boot.ini") Console.WriteLine(sr.ReadToEnd)Catch ex As Exception ' If there are any problems reading the file, display an error message Console.WriteLine("Error reading file: " + ex.Message)End Try // C#try{ StreamReader sr = new StreamReader(@"C:\boot.ini"); Console.WriteLine(sr.ReadToEnd());} catch (Exception ex){ // If there are any problems reading the file, display an error message Console.WriteLine("Error reading file: " + ex.Message);}
In the preceding example, if any type of error occurs—including a file not found error, insufficient privileges error, or an error during the reading of the file—processing continues within the Catch block. If no problems occur, the runtime skips the Catch block.
The base Exception class is very useful and contains an error message and other application data. In addition to the base Exception class, the Framework defines hundreds of exception classes to describe different types of events, all derived from System.SystemException. Additionally, you can define your own exceptions when you need to describe an event in more detail than allowed by the standard exception classes by deriving from System.ApplicationException.
拥有不同的异常类,允许你响应不同类型的错误. 运行环境将只执行第一个匹配异常类型的 Catch 块, however, so order Catch blocks from the most-specific to the least-specific. The following code sample displays different error messages for a file not found error, an insufficient privileges error, and any other type of error that might occur:
' VBTry Dim sr As StreamReader = New StreamReader("text.txt") Console.WriteLine(sr.ReadToEnd)Catch ex As System.IO.FileNotFoundException Console.WriteLine("The file could not be found.")Catch ex As System.UnauthorizedAccessException Console.WriteLine("You do not have sufficient permissions.")Catch ex As Exception Console.WriteLine("Error reading file: " + ex.Message)End Try
This process is sometimes called filtering exceptions. Exception handling also supports a Finally block. The Finally block runs after the Try block and any Catch blocks have finished executing, whether or not an exception was thrown. Therefore, you should use a Finally block to close any streams or clean up any other objects that might be left open if an exception occurs. The following code sample closes the StreamReader object whether or not an exception occurs:
' VBDim sr As StreamReader = New StreamReader("text.txt")Try Console.WriteLine(sr.ReadToEnd) Catch ex As Exception ' If there are any problems reading the file, display an error message Console.WriteLine("Error reading file: " + ex.Message)Finally ' Close the StreamReader, whether or not an exception occurred sr.CloseEnd Try // C#StreamReader sr = new StreamReader("text.txt");try{ Console.WriteLine(sr.ReadToEnd());}catch (Exception ex){ // If there are any problems reading the file, display an error message Console.WriteLine("Error reading file: " + ex.Message);}finally{ // Close the StreamReader, whether or not an exception occurred sr.Close(); //(译者注:其实把sr定义到try外面并不好,我们关闭sr时,可以加一个判断,如下: //if(sr != null) sr.close(); //)}
Notice that the StreamReader declaration was moved outside the Try block in the preceding example. This is necessary because the Finally block cannot access variables that are declared within the Try block. This makes sense because depending on where an exception occurred, variable declarations within the Try block might not yet have been executed. To catch exceptions that occur both during and after the StreamReader declaration, use nested Try/Catch/Finally blocks.
Typically, all code except for simple variable declarations should occur within Try blocks. Robust error handling improves the user experience when problems occur and greatly simplifies debugging problems. However, exception handling does incur a slight performance penalty. To conserve space and focus on specific topics, sample code within this book will typically not include exception handling.
Working with Reference Types
In this exercise, you will write a console application that displays whether objects are value or reference types.
Using Visual Studio, create a new console application project. Name the project List-Value-Types.
Create instances of the following classes:
SByte
Byte
Int16
Int32
Int64
String
Exception
The following code demonstrates this:
' VBDim a As SByte = 0Dim b As Byte = 0Dim c As Int16 = 0Dim d As Int32 = 0Dim e As Int64 = 0Dim s As String = ""Dim ex As Exception = New Exception // C#SByte a = 0;Byte b =0;Int16 c = 0;Int32 d = 0;Int64 e = 0;string s = "";Exception ex = new Exception();
Add each of the instances to a new object array, as the following code demonstrates:
' VBDim types As Object() = {a, b, c, d, e, s, ex} // C#object[] types = { a, b, c, d, e, s, ex };
Within a foreach loop, check the object.GetType().IsValueType property to determine whether the type is a value type. Display each type name and whether it is a value type or a reference type, as the following code demonstrates:
' VBFor Each o As Object In types Dim type As String If o.GetType.IsValueType Then type = "Value type" Else type = "Reference Type" End If Console.WriteLine("{0}: {1}", o.GetType, type)Next // C#foreach ( object o in types ){ string type; if (o.GetType().IsValueType) type = "Value type"; else type = "Reference Type"; Console.WriteLine("{0}: {1}", o.GetType(), type);}
Run the console application, and verify that each type matches your understanding.
在这里练习里面,你将编写一个函数来排序字符串.
Using Visual Studio, create a new console application project. Name the project SortString.
Define a string. Then use the String.Split method to separate the string into an array of words. The following code demonstrates this:
' VBDim s As String = "Microsoft .NET Framework 2.0 Application Development Foundation"Dim sa As String() = s.Split(" ") // C#string s = "Microsoft .NET Framework 2.0 Application Development Foundation";string[] sa = s.Split(' ');
Call the Array.Sort method to sort the array of words, as the following code demonstrates:
' VBArray.Sort(sa) // C#Array.Sort(sa);
Call the String.Join method to convert the array of words back into a single string, and then write the string to the console. The following code sample demonstrates this:
' VBs = String.Join(" ", sa)Console.WriteLine(s) // C#s = string.Join(" ", sa);Console.WriteLine(s);
Run the console application, and verify that it works correctly.
Consider a scenario(情节) in which a coworker wrote a simple Windows Forms application to view text files. However, users complain that it is very temperamental(喜怒无常的). If the user mistypes the filename or if the file is not available for any reason, the application fails with an unhandled exception error. You must add exception handling to the application to display friendly error messages to users if a file is not available.
Copy the Chapter01\Lesson2-ViewFile folder from the companion CD to your hard disk, and open either the C# version or the Visual Basic .NET version of the ViewFile project.
Exceptions occur when users attempt to view a file. Therefore, edit the code that runs for the showButton.Click event. Add code to catch any type of exception that occurs, and display the error in a dialog box to the user. If an exception occurs after the TextReader object is initialized, you should close it whether or not an exception occurs. You will need two nested Try blocks: one to catch exceptions during the TextReader initialization, and a second one to catch exceptions when the file is read. The following code sample demonstrates this:
' VBTry Dim tr As TextReader = New StreamReader(locationTextBox.Text) Try displayTextBox.Text = tr.ReadToEnd Catch ex As Exception MessageBox.Show(ex.Message) Finally tr.Close() End TryCatch ex As Exception MessageBox.Show(ex.Message)End Try // C#try{ TextReader tr = new StreamReader(locationTextBox.Text); try { displayTextBox.Text = tr.ReadToEnd(); } catch (Exception ex) { MessageBox.Show(ex.Message); } finally { tr.Close(); }}catch (Exception ex){ MessageBox.Show(ex.Message); }
Run your application. First verify that it can successfully display a text file. Then provide an invalid filename, and verify that a message box appears when an invalid filename is provided.
Next add overloaded exception handling to catch System.IO.FileNotFoundException and System.UnauthorizedAccessException. The following code sample demonstrates this:
' VBTry Dim tr As TextReader = New StreamReader(locationTextBox.Text) Try displayTextBox.Text = tr.ReadToEnd Catch ex As Exception MessageBox.Show(ex.Message) Finally tr.Close() End TryCatch ex As System.IO.FileNotFoundException MessageBox.Show("Sorry, the file does not exist.")Catch ex As System.UnauthorizedAccessException MessageBox.Show("Sorry, you lack sufficient privileges.")Catch ex As Exception MessageBox.Show(ex.Message)End Try // C#try{ TextReader tr = new StreamReader(locationTextBox.Text); try { displayTextBox.Text = tr.ReadToEnd(); } catch (Exception ex) { MessageBox.Show(ex.Message); } finally { tr.Close(); }}catch (System.IO.FileNotFoundException ex){ MessageBox.Show("Sorry, the file does not exist."); }catch (System.UnauthorizedAccessException ex){ MessageBox.Show("Sorry, you lack sufficient privileges."); }catch (Exception ex){ MessageBox.Show(ex.Message); }
Run your application again, and verify that it provides your new error message if an invalid filename is provided.
课程概要
引用类型保存数据的地址而不是数据本身
当你复制一个值类型时,这个值的副本已经建立了. 当你复制一个引用类型时, 仅仅复制了指针. 因此, 如果你复制了一个引用类型,并修改了这个副本, 那么这个副本和所有的原始数据都被修改了.
.NET Framework 包含了很多内建的引用类型,你可以直接使用,或者创建自己的引用类型.
Strings 是不可变的; 用StringBuilder 来创建动态的字符串.
用streams 来读写 files, memory, 和 network.
用 Catch 来 过滤 exceptions . 在Finally 语句里面关闭所有资源。
课程复习
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. |
1. |
Which of the following are reference types? (Choose all that apply.)
|
|
2. |
What is the correct order for Catch clauses when handling different exception types?
|
|
3. |
When should you use the StringBuilder class instead of the String class?
|
|
4. |
Why should you close and dispose of resources in a Finally block instead of a Catch block?
|
Answers
1. |
Correct Answers: B and C
|
2. |
Correct Answer: C
|
3. |
Correct Answer: A
|
4. |
Correct Answer: B
|
转载于:https://www.cnblogs.com/nevernet/archive/2008/09/17/1292386.html
Chapter 1: 使用引用类型相关推荐
- 《JavaScript高级程序设计》Chapter 5 引用类型
Chapter 5 引用类型 使用表格进行归纳,对表格中某些内容会进行必要解释,并把解释放在表格下方. Object类型 Array类型 Date类型 RegExp类型 Function类型 基本 ...
- swift string转int_swift中结构体和类的区别(值类型和引用类型的区别)
在swift中结构体和类有着更多的相同之处,在一般的使用中能够做到互相替换.我们可以先看看官方文档的描述: Unlike other programming languages, Swift does ...
- 《C++ Templates》笔记 Chapter 12 Fundamentals in Depth-Chapter 13 Names in Templates
文章目录 Chapter 12 Fundamentals in Depth 12.1 Parameterized Declarations 12.1.1 Virtual Member Function ...
- 引用和指针的区别都有什么_为什么要有指针和引用类型?
--显然,我们能通过名字使用对象.然而在 C++ 中,大多数对象都"有身份":也就是说对象位于内存的某个地址中,如果我们知道对象的地址和类型,就能访问它--翻译自 Bjarne S ...
- JS引用类型(6)——基本包装类型1
[6]基本包装类型 3个特殊的引用类型:Boolean.Number.String. 每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而让我们能够调用一些方法来操作这些数据. ...
- c# 垃圾回收是引用类型而言的
c# 垃圾回收是引用类型而言的 转载于:https://www.cnblogs.com/C-CHERS/p/3646387.html
- JS基础类型和引用类型
JS基础类型和引用类型脑图
- Swift 值类型和引用类型的内存管理
1.内存分配 1.1 值类型的内存分配 在 Swift 中定长的值类型都是保存在栈上的,操作时不会涉及堆上的内存.变长的值类型(字符串.集合类型是可变长度的值类型)会分配堆内存. 这相当于一个 &qu ...
- 微软在C# 8中引入预览版可空引用类型
微软已经为开发者提供了预览版的可空引用类型(Nullable Reference Type),想尝鲜的开发者可以尝试这个新特性,并提供反馈. \\ 预览版可空引用类型是Visual Studio 20 ...
最新文章
- 20分钟教你搞懂Git!
- docker image镜像的发布
- 湖南2021年计算机一级考试,2021年湖南计算机一级考试时间(4页)-原创力文档...
- OpencvSharp的踩坑之路
- 汇编 if else
- wait和notify使用例子
- 深入react技术栈(7):组件化实例:Tab栏组件
- 想尝试搭建图像识别系统?这里有一份TensorFlow速成教程
- 三种方法进行分水岭分割
- [C++]最大连续子序列乘积
- Fragment中获取Activity的Context
- 教学:四步利用PHP study小皮面板在vscode上编辑php并运行
- rar、zip、7z等压缩率的测试
- IEEE 754 32bit浮点标识
- ElasticSearch简介及ElasticSearch部署、原理和使用介绍
- 2.45GHz天线初始尺寸设定
- 互联网拓扑是怎样构成的?又代表了什么?
- MySQL8免安装版下载安装与配置(linux)
- LeetCode 101:和你一起你轻松刷题(C++)总篇章正在陆续更新
- 数据通信与网络(一)