本页内容
简介
Visual C# .NET 是 Visual Studio
系列中的最新成员。这种新语言基于 C/C++,但它深化了更容易地使用面向组件编程的发展方向。C/C++
程序员应该非常熟悉它的语法。
下面的示例应用程序示范了如何构建一个简单的实现
QuickSort 算法的 C# 项目。它包括了 C#
程序的基本组成部分:读/写控制台和文件、创建函数和使用基本数组。
这些入门指南并不打算涵盖该编程语言的所有方面。它们只是您探索这种语言的一个起点。我们鼓励您按照本教程的说明执行,因为它包括了
QuickSort
应用程序的各个不同部分。您还可以获得完整的源代码和项目文件。
建议的要求
编译此示例应用程序需要 Visual Studio.NET(测试版 2
或更高版本)。关于 C/C++
的知识是有帮助的但不是必需的。
步骤 1. 开始项目
Visual Studio
中的开发工作以解决方案的形式进行组织,每个解决方案包含一个或多个项目。在本教程中,我们创建的解决方案包含一个
C# 项目。
创建一个新项目
1.
|
在 Visual Studio .NET 环境中,从菜单中选择 File
| New | Project。
|
2.
|
在左侧选择 Visual C#Projects,然后在右侧选择
Console Application。
|
3.
|
指定项目的名称,然后输入创建项目的位置。Visual
Studio 会自动创建项目目录。
|
4.
|
单击 OK,那么现在就正式开始了!
|
Visual C# 解决方案
Visual Studio.NET 已经创建了含有一个简单 Visual C#
项目的解决方案。该项目包含两个文件:assemblyinfo.cs
和 class1.cs。
接下来的几步骤将讨论这些不同的文件以及如何编译该项目。
步骤 2. Hello, World!
很遗憾,但我们仍然无法抵御这种诱惑……我们还是不得不完成一个基于
C# 的经典"Hello, World!"应用程序,这个应用程序最初是用
C 语言编写的。
修改源代码
1.
|
在 Solution Explorer 中双击文件"class1.cs"。可以通过"View"菜单来显示
Solution Explorer。
|
2.
|
更改预生成的模板 (class1.cs),如下面以斜体突出显示的
代码所示。
using System;
namespace quicksort
{
///
/// Summary description for Class1.
///
class Class1
{
static void Main(string[] args)
{
//
// TODO: Add code to start application here
//
Console.WriteLine ("Hello, C#.NET World!");
}
}
}
|
3.
|
注意,当您键入代码时,Visual Studio
将为您提示类和函数的名称(因为 .NET
框架发布了这种类型信息)。
|
编译应用程序
1.
|
既然您已经完成了修改,就可以通过在 Build
菜单中简单地选择 Build 来编译 Visual C# 项目。
|
2.
|
来自 C# 编译器的错误和消息会在 Output
窗口中显示。如果没有错误,则可以通过单击
Debug 菜单下的 Start without Debugging 来运行 Hello
World 应用程序。
|
程序输出
在 Visual C# 中运行 Hello World
示例应用程序时,输出结果的屏幕截图如下:
理解更改
System.Console 类的 WriteLine() 函数打印传递给它的字符串,其后紧跟一行新的字符。此函数可以接受许多其他数据类型(包括整型和浮点型)的参数。
在程序加载完成后,控制就传递给 Main() 函数。这就是我们在该过程中插入对
WriteLine() 调用的原因。
步骤 3. 程序结构
既然我们已经构建了一个简单的 Hello World
应用程序,那么就让我们停下来分析一下 Visual C#
应用程序的基本组成部分。
源代码注释
字符 // 将行的剩余部分标记为一个注释,这样 C#
编译器就会忽略它。另外,/* 和 */
之间的代码也会被当作注释。
// This line is ignored by the compiler.
/* This block of text is also
ignored by the Visual C# compiler. */
Using 指令
.NET 框架为开发人员提供了许多有用的类。例如,Console
类处理对控制台窗口的输入和输出。这些类是按照层次树的形式组织的。Console
类的完全限定名实际上是 System.Console。其他的类包括
System.IO.FileStream 和 System.Collections.Queue。
using
指令允许您在不使用完全限定名的情况下引用命名空间中的类。以斜体突出显示的
代码应用了 using 指令。
using System;
class Class1
{
static void Main(string[] args)
{
System.Console.WriteLine ("Hello, C#.NET World!");
Console.WriteLine ("Hello, C#.NET World!");
}
}
类声明
与 C++ 或 Visual Basic 不同,Visual C#
中的所有函数都必须封装在一个类中。class
语句声明一个新的 C# 类。就 Hello World
应用程序来说,Class1 类包含一个函数,即 Main()
函数。如果用一个 namespace
块将类的定义括起来,就可以把类组织为诸如 MsdnAA.QuickSortApp
这样的层次。
在本入门指南中,我们并不打算深入地介绍类,但是我们将为您简要概述为什么类是我们的示例应用程序的一部分。
Main() 函数
在应用程序加载到内存之后,Main() 函数就会接收控制,因此,应该将应用程序启动代码放在此函数中。传递给程序的命令行参数存储在
args 字符串数组中。
步骤 4. 控制台输入
现在,我们将继续编写 QuickSort
应用程序。我们需要做的第一件事就是提示用户提供输入和输出文件。
修改源代码
更改 C# 源文件 (class1.cs),如下面以斜体突出显示的代码所示。其他的差异(如类名)可忽略不计。
// Import namespaces
using System;
// Declare namespace
namespace MsdnAA
{
// Declare application class
class QuickSortApp
{
// Application initialization
static void Main (string[] szArgs)
{
// Describe program function
Console.WriteLine ("QuickSort C#.NET Sample Application\n");
// Prompt user for filenames
Console.Write ("Source: ");
string szSrcFile = Console.ReadLine ();
Console.Write ("Output: ");
string szDestFile = Console.ReadLine ();
}
}
}
从控制台进行读取
Console 类的 ReadLine() 方法提示用户输入,并返回输入的字符串。它会自动地为字符串处理内存分配,由于使用了
.NET 垃圾回收器,您不需要做任何释放内存的工作。
程序输出
从菜单中选择 Debug | Start Without Debugging 来运行程序。这是到此为止来自
QuickSort 应用程序的输出的屏幕截图。
步骤 5. 使用数组
在对从输入读取的行进行排序之前,程序需要将其存储到一个数组中。我们将简要讨论可实现对象数组的
.NET 基类的用法。
修改源代码
更改 C# 源文件 (class1.cs),如下面以斜体突出显示的代码所示。其他的差异(如类名)可忽略不计。
// Import namespaces
using System;
using System.Collections;
// Declare namespace
namespace MsdnAA
{
// Declare application class
class QuickSortApp
{
// Application initialization
static void Main (string[] szArgs)
{
// Describe program function
Console.WriteLine ("QuickSort C#.NET Sample Application\n");
// Prompt user for filenames
Console.Write ("Source: ");
string szSrcFile = Console.ReadLine ();
Console.Write ("Output: ");
string szDestFile = Console.ReadLine ();
// TODO: Read contents of source file
ArrayList szContents = new ArrayList ();
}
}
}
使用 ArrayList 类
我们将导入 System.Collections
命名空间,这样我们就可以直接引用 ArrayList。此类实现大小可动态调整的对象数组。要插入新的元素,可以简单地将对象传递到
ArrayList 类的 Add() 方法。新的数组元素将引用原始的对象,而垃圾回收器将处理它的释放。
string szElement = "insert-me";
ArrayList szArray = new ArrayList ();
szArray.Add (szElement);
要检索现有的元素,请将所需元素的索引传递给 Item()
方法。另外,作为一种简写形式,还可以使用方括号
operator [],它实际上映射到 Item() 方法。
Console.WriteLine (szArray[2]);
Console.WriteLine (szArray.Item (2));
ArrayList
类中还有许多其他方法,但是插入和检索都是我们需要在此示例中使用的。请查阅
MSDN 库以获得完整的参考指南。
步骤 6. 文件输入/输出
现在,让我们来实现读取输入文件和写入输出文件。我们将每一行读取到一个字符串数组中,然后输出该字符串数组。在下一步中,我们将使用
QuickSort 算法来对该数组进行排序。
修改源代码
更改 C# 源文件 (class1.cs),如下面以斜体突出显示的代码所示。其他的差异(如类名)可忽略不计。
// Import namespaces
using System;
using System.Collections;
using System.IO;
// Declare namespace
namespace MsdnAA
{
// Declare application class
class QuickSortApp
{
// Application initialization
static void Main (string[] szArgs)
{
... ... ...
// Read contents of source file
string szSrcLine;
ArrayList szContents = new ArrayList ();
FileStream fsInput = new FileStream (szSrcFile, FileMode.Open,
FileAccess.Read);
StreamReader srInput = new StreamReader (fsInput);
while ((szSrcLine = srInput.ReadLine ()) != null)
{
// Append to array
szContents.Add (szSrcLine);
}
srInput.Close ();
fsInput.Close ();
// TODO: Pass to QuickSort function
// Write sorted lines
FileStream fsOutput = new FileStream (szDestFile,
FileMode.Create, FileAccess.Write);
StreamWriter srOutput = new StreamWriter (fsOutput);
for (int nIndex = 0; nIndex < szContents.Count; nIndex++)
{
// Write line to output file
srOutput.WriteLine (szContents[nIndex]);
}
srOutput.Close ();
fsOutput.Close ();
// Report program success
Console.WriteLine ("\nThe sorted lines have been written.\n\n");
}
}
}
从源文件进行读取
使用 FileStream 类打开源文件,然后加入 StreamReader
类,这样我们就可以使用它的 ReadLine() 方法了。现在,我们调用
ReadLine() 方法,直到它返回 null,这表示到达文件结尾。在循环过程中,我们将读取的行存储到字符串数组中,然后关闭这两个对象。
写入输出文件
假设已经用 QuickSort
对字符串数组进行了排序,接下来要做的事情就是输出数组的内容。按照同样的方式,我们将
StreamWriter 对象附加到 FileStream
对象上。这使得我们可以使用 WriteLine() 方法,该方法能够很方便地模仿
Console
类的行为。一旦遍历了数组,我们便可以象前面一样关闭这两个对象。
步骤 7. 创建函数
最后一步就是创建一个函数来在字符串数组中运行
QuickSort。我们将此函数放到应用程序类 QuickSortApp
之中。
修改源代码
更改 C# 源文件 (class1.cs),如下面以斜体突出显示的
代码所示。其他的差异(如类名)可忽略不计。
// Import namespaces
using System;
using System.Collections;
using System.IO;
// Declare namespace
namespace MsdnAA
{
// Declare application class
class QuickSortApp
{
// Application initialization
static void Main (string[] szArgs)
{
... ... ...
// Pass to QuickSort function
QuickSort (szContents, 0, szContents.Count - 1);
... ... ...
}
// QuickSort implementation
static void QuickSort (ArrayList szArray, int nLower, int nUpper)
{
// Check for non-base case
if (nLower < nUpper)
{
// Split and sort partitions
int nSplit = Partition (szArray, nLower, nUpper);
QuickSort (szArray, nLower, nSplit - 1);
QuickSort (szArray, nSplit + 1, nUpper);
}
}
// QuickSort partition implementation
static int Partition (ArrayList szArray, int nLower, int nUpper)
{
// Pivot with first element
int nLeft = nLower + 1;
string szPivot = (string) szArray[nLower];
int nRight = nUpper;
// Partition array elements
string szSwap;
while (nLeft <= nRight)
{
// Find item out of place
while (nLeft <= nRight)
{
if (((string) szArray[nLeft]).CompareTo (szPivot) > 0)
break;
nLeft = nLeft + 1;
}
while (nLeft <= nRight)
{
if (((string) szArray[nRight]).CompareTo (szPivot) <= 0)
break;
nRight = nRight - 1;
}
// Swap values if necessary
if (nLeft < nRight)
{
szSwap = (string) szArray[nLeft];
szArray[nLeft] = szArray[nRight];
szArray[nRight] = szSwap;
nLeft = nLeft + 1;
nRight = nRight - 1;
}
}
// Move pivot element
szSwap = (string) szArray[nLower];
szArray[nLower] = szArray[nRight];
szArray[nRight] = szSwap;
return nRight;
}
}
}
QuickSort() 函数
这个函数需要三个参数:对数组的引用、下界和上界。它调用
Partition() 函数将数组分成两部分,其中一部分包含
Pivot 值之前的所有字符串,另一部分包含 Pivot
值之后的所有字符串。然后,它调用自身来对每个部分进行排序。
上面修改中的注释应该说明了每个代码块的作用。唯一的新概念就是
CompareTo() 方法的使用,该方法是 String
类的成员,并且应该是自说明的。
运行 QuickSort 应用程序
这一步完成 QuickSort C#
示例应用程序。现在,可以构建项目并运行应用程序。需要提供一个示例文本文件,以供其进行排序。将该文件放在与
EXE 文件相同的目录中。
程序输出
下面是已完成的 QuickSort C# .NET
示例应用程序的输出。可以查看示例输入文件 'example.txt'
和输出文件 'output.txt'。
步骤 8. 使用调试器
调试器是诊断程序问题的一个必不可少的工具。我们觉得有必要在本入门指南中对其进行介绍。这最后一步将向您展示如何走查程序和使用诸如
QuickWatch 这样的功能。
设置断点
当程序在调试器中运行时,断点会暂停程序的执行,从而使开发人员能够控制调试器。要设置断点,请右键单击您想要程序暂停的行,然后单击
InsertBreakpoint,如下所示。
注:带有断点的行以红色突出显示。通过再次右键单击该行并选择
Remove Breakpoint 可以删除断点。
单步调试程序
既然设置了断点(最好是在前面所示的行中),就让我们在调试器中运行程序。在
Debug 菜单中,选择 Start
而不是同前面一样选择 Start Without Debugging。这样就在调试器中启动了程序,并因而激活了断点。
一旦程序遇到断点,调试器便会接收程序的控制。这时会有一个箭头指向当前执行的行。
要单步调试一行代码,可以选择 Debug | Step Over
并观察光标是否移到下一行。Debug | Step Into
命令允许您单步执行将要调用的函数。进行两次 Step
Over 之后的屏幕如下所示。
如果想要程序在遇到下一个断点、遇到异常或退出之前继续执行,请从菜单中选择
Debug | Continue。
检查变量值
当您可以控制调试器时,可将鼠标指针移到变量上以获得它的基本值。
您也可以右键单击变量,然后从上下文菜单中选择
QuickWatch。QuickWatch
将为您提供关于某些变量(如 ArrayList
对象)的更多详细信息。
其他调试器工具
Visual Studio 调试器具有许多其他工具(例如 Call
Stack
查看器)的功能,可以使用此调试器来查看到此为止调用的函数。还可以获得内存转储和关于进程中线程的信息。我们鼓励您使用这些功能强大的调试工具。
小结
本入门指南旨在帮助您用 Visual Studio
构建一个简单的 C#
项目。它无法进行全面的介绍。我们鼓励您查询关于
C# 和 .NET
的其他资源,以便更多地学习这些技术。在完成本教程之后,您至少有了一个可用的项目,在您研究
Visual C# 时,可以从修改此这些代码开始。
为了方便起见,我们提供了完整的源程序和项目文件。您可以通过本文档顶部的目录来访问它们。
其他资源
我们强烈推荐下面这些关于 C# 和 .NET
平台的书籍。它们是开发人员尝试学习这些新技术的有益资源。
• |
Archer, Tom.Inside C#.Redmond:Microsoft Press,
2001.
|
• |
Deitel, Harvey.C#:How to Program.Upper Saddle
River, NJ:Prentice Hall, 2001.
|
• |
Gunnerson, Eric.A Programmer's Introduction to C#.New
York:Apress, 2000.
|
• |
Platt, David.Introducing Microsoft .NET.Redmond:Microsoft
Press, 2001.
|
补遗:QuickSort C# .NET 的源代码
下面是 QuickSort C# .NET
示例应用程序的完整源代码。您可以复制、使用和分发这些代码(无版权费)。注意,这些源代码以"原样"提供并且不作任何保证。
//
// QuickSort C# .NET Sample Application
// Copyright 2001-2002 Microsoft Corporation. All rights reserved.
//
// MSDN ACADEMIC ALLIANCE [http://www.msdn.microsoft.com/academic]
// This sample is part of a vast collection of resources we developed for
// faculty members in K-12 and higher education. Visit the MSDN AA web site for more!
// The source code is provided "as is" without warranty.
//
// Import namespaces
using System;
using System.Collections;
using System.IO;
// Declare namespace
namespace MsdnAA
{
// Declare application class
class QuickSortApp
{
// Application initialization
static void Main (string[] szArgs)
{
// Print startup banner
Console.WriteLine ("\nQuickSort C#.NET Sample Application");
Console.WriteLine ("Copyright (c)2001-2002 Microsoft Corporation. All rights reserved.\n");
Console.WriteLine ("MSDN ACADEMIC ALLIANCE [http://www.msdnaa.net/]\n");
// Describe program function
Console.WriteLine ("This example demonstrates the QuickSort algorithm by reading an input file,");
Console.WriteLine ("sorting its contents, and writing them to a new file.\n");
// Prompt user for filenames
Console.Write ("Source: ");
string szSrcFile = Console.ReadLine ();
Console.Write ("Output: ");
string szDestFile = Console.ReadLine ();
// Read contents of source file
string szSrcLine;
ArrayList szContents = new ArrayList ();
FileStream fsInput = new FileStream (szSrcFile, FileMode.Open, FileAccess.Read);
StreamReader srInput = new StreamReader (fsInput);
while ((szSrcLine = srInput.ReadLine ()) != null)
{
// Append to array
szContents.Add (szSrcLine);
}
srInput.Close ();
fsInput.Close ();
// Pass to QuickSort function
QuickSort (szContents, 0, szContents.Count - 1);
// Write sorted lines
FileStream fsOutput = new FileStream (szDestFile, FileMode.Create, FileAccess.Write);
StreamWriter srOutput = new StreamWriter (fsOutput);
for (int nIndex = 0; nIndex < szContents.Count; nIndex++)
{
// Write line to output file
srOutput.WriteLine (szContents[nIndex]);
}
srOutput.Close ();
fsOutput.Close ();
// Report program success
Console.WriteLine ("\nThe sorted lines have been written to the output file.\n\n");
}
// QuickSort implementation
private static void QuickSort (ArrayList szArray, int nLower, int nUpper)
{
// Check for non-base case
if (nLower < nUpper)
{
// Split and sort partitions
int nSplit = Partition (szArray, nLower, nUpper);
QuickSort (szArray, nLower, nSplit - 1);
QuickSort (szArray, nSplit + 1, nUpper);
}
}
// QuickSort partition implementation
private static int Partition (ArrayList szArray, int nLower, int nUpper)
{
// Pivot with first element
int nLeft = nLower + 1;
string szPivot = (string) szArray[nLower];
int nRight = nUpper;
// Partition array elements
string szSwap;
while (nLeft <= nRight)
{
// Find item out of place
while (nLeft <= nRight && ((string) szArray[nLeft]).CompareTo (szPivot) <= 0)
nLeft = nLeft + 1;
while (nLeft <= nRight && ((string) szArray[nRight]).CompareTo (szPivot) > 0)
nRight = nRight - 1;
// Swap values if necessary
if (nLeft < nRight)
{
szSwap = (string) szArray[nLeft];
szArray[nLeft] = szArray[nRight];
szArray[nRight] = szSwap;
nLeft = nLeft + 1;
nRight = nRight - 1;
}
}
// Move pivot element
szSwap = (string) szArray[nLower];
szArray[nLower] = szArray[nRight];
szArray[nRight] = szSwap;
return nRight;
}
}
}
补遗:关于 QuickSort C# .NET
为了演示 QuickSort Visual C# .NET 示例应用程序实际是如何运行的,我们提供了编译好的可执行文件。您可以通过编译这些项目文件来创建自己的可执行文件。单击
Quicksort_Visual_CSharp_.NET.exe,下载源代码项目文件和可执行文件包。
使用应用程序
启动 Command Prompt(从"开始"菜单运行"cmd.exe")。使用
CD
命令将目录更改为可执行文件所在的目录。然后运行"quicksort.exe"。
程序将提示您提供输入和输出文件的名称。任何包含多行的文本文件均可使用。如果需要,可以使用记事本来创建一个此类文件。然后,该程序将对输入文件的内容进行排序,并且将其写入输出文件。
示例程序输出
下面是来自此 QuickSort C# .NET
应用程序的一个实例的输出。此示例演示了 QuickSort
算法,方法是读取输入文件、对文件的内容进行排序,然后将其写入新的文件。用户输入的文本以下划线标记。
您可以查看下面的示例输入文件 'example.txt' 和输出文件 'output.txt'。
QuickSort C# .NET Sample Application
Copyright (c)2001-2002 Microsoft Corporation. All rights reserved.
MSDN ACADEMIC ALLIANCE [http://www.msdn.microsoft.com/academic]
This example demonstrates the QuickSort algorithm by reading an input file,
sorting its contents, and writing them to a new file.
Source: example.txt
Output: output.txt
The sorted lines have been written to the output file.
查看示例输入文件"example.txt":
Visual C#
Windows Embedded
JavaScript
Speech API
ASP.NET
VBScript
Windows Media
Visual Basic
.NET Framework
BizTalk Server
XML Parser
Internet Explorer
Visual C#
SQL Server
Windows XP
DirectX API
查看示例输出文件"output.txt":
.NET Framework
ASP.NET
BizTalk Server
DirectX API
Internet Explorer
JavaScript
Speech API
SQL Server
VBScript
Visual Basic
Visual C#
Visual C#
Windows Embedded
Windows Media
Windows XP
XML Parser
|