博文

C# 程序员参考--不安全代码教程(2006-09-03 18:25:00)

摘要:该教程说明如何在 C# 中使用不安全代码(使用指针的代码)。 教程
在 C# 中很少需要使用指针,但仍有一些需要使用的情况。例如,在下列情况中使用允许采用指针的不安全上下文是正确的: 处理磁盘上的现有结构
涉及内部包含指针的结构的高级 COM 或平台调用方案
性能关键代码
不鼓励在其他情况下使用不安全上下文。具体地说,不应该使用不安全上下文尝试在 C# 中编写 C 代码。 警告   使用不安全上下文编写的代码无法被验证为安全的,因此只有在代码完全受信任时才会执行该代码。换句话说,不可以在不受信任的环境中执行不安全代码。例如,不能从 Internet 上直接运行不安全代码。
该教程包括下列示例: 示例 1   使用指针复制一个字节数组。
示例 2   显示如何调用 Windows ReadFile 函数。
示例 3   显示如何打印可执行文件的 Win32 版本。
示例 1
以下示例使用指针将一个字节数组从 src 复制到 dst。用 /unsafe 选项编译此示例。 // fastcopy.cs
// compile with: /unsafe
using System;
 
class Test
{
    // The unsafe keyword allows pointers to be used within
    // the following method:
    static unsafe void Copy(byte[] src, int srcIndex,
        byte[] dst, int dstIndex, int count)
    {
        if (src == null || srcIndex < 0 ||
......

阅读全文(1138) | 评论:0

C# 程序员参考--线程处理教程(2006-09-03 18:25:00)

摘要:线程处理的优点是可以创建使用多个执行线程的应用程序。例如,某一进程可以具有管理与用户交互的用户界面线程,以及在用户界面线程等待用户输入时执行其他任务的辅助线程。 该教程说明各种线程活动: 创建和执行线程 线程同步 线程间交互 使用线程池 使用 mutex 对象保护共享资源 教程 该教程包含下列示例: 示例 1:创建线程、启动线程和线程间交互 示例 2:同步两个线程:制造者和使用者 示例 3:使用线程池 示例 4:使用 Mutex 对象 示例 1:创建线程、启动线程和线程间交互 本示例说明如何创建和启动线程,并显示了同时在同一进程内运行的两个线程间的交互。请注意,不必停止或释放线程。这由 .NET Framework 公共语言运行库自动完成。 程序从创建 Alpha 类型的对象 (oAlpha) 和引用 Alpha 类的 Beta 方法的线程 (oThread) 开始。然后启动该线程。线程的 IsAlive 属性允许程序等待,直到线程被初始化(被创建、被分配等)为止。主线程通过 Thread 访问,而 Sleep 方法通知线程放弃其时间片并在一定毫秒数期间停止执行。然后 oThread 被停止和联接。联接一个线程将使主线程等待它死亡或等待它在指定的时间后过期。最后,程序尝试重新启动 oThread,但由于线程无法在停止(中止)后重新启动而告失败。有关临时停止执行的信息,请参见挂起线程执行。// StopJoin.cs using System; using System.Threading; public class Alpha { // This method that will be called when the thread is started public void Beta() { while (true) { Console.WriteLine("Alpha.Beta is running in its own thread."); } } }; public class Simple { public static int Main() { C......

阅读全文(1107) | 评论:0

C# 程序员参考--安全性教程(2006-09-03 18:23:00)

摘要:本教程讨论了 .NET Framework 安全性并显示了在 C# 修改安全权限的两种方式:命令性安全和声明性安全。 教程 大多数应用程序和组件开发人员不需完成任何特别的工作就可使用 .NET Framework 安全系统并从它所提供的安全保护中受益。 但“安全库”是一个例外,它要求了解更多深入的知识并对安全系统加以特殊考虑。这些代码表明了安全托管代码与非限制代码之间的界限,后者如本机代码(这超出了 .NET Framework 安全基础结构可以强制的范围)。这些库通常必须受到高度信任才可以工作,它们是托管代码中编程错误会潜在地暴露安全隐患的一个位置。代码访问安全性无法消除人为错误的可能性,但相对于使用几个安全库的大量应用程序代码而言,需要严格审查的代码量将大大减少。 示例 该教程包括下列示例: 示例 1:强制式安全性 示例 2:声明式安全性 示例 3:禁止安全性 安全性 .NET Framework 安全性通过在托管代码上强制实施安全限制来防止其他代码误用或破坏您的代码和数据。当 .NET Framework 应用程序请求权限时,由管理员建立的安全策略将授予权限或拒绝运行代码。信任是基于有关代码的证据(如数字签名、代码来自何处等)的。一旦授予权限,安全性就会实施控制这些代码可以做什么(或如果未授予权限,则控制代码不能做什么)的权限。 权限 .NET Framework 安全性只有当代码具有使用受保护资源的“权限”时才允许它使用这些资源。为了表示此情形,.NET Framework 使用了“权限”的概念,它表示代码访问受保护资源的权力。代码请求所需的权限,然后由 .NET Framework 应用的安全策略确定实际授予代码哪些权限。 .NET Framework 提供了代码访问权限类,其中每个类都封装了访问某一特定资源的能力。使用这些权限向 .NET Framework 指示需要允许代码做什么以及必须授权代码的调用方做什么。策略还使用这些对象确定要向代码授予哪些权限。 策略 安全策略的强制性保证了 .NET Framework 托管代码的安全。每个加载的程序集都受到安全策略的约束,安全策略基于信任授予代码权限,而信任又是基于有关代码的证据的。有关管理安全策略的信息,请参见“阅读材料列表”中的 .NET Framework 文......

阅读全文(1358) | 评论:0

C# 程序员参考--属性教程(2006-09-03 18:22:00)

摘要:本教程展示如何创建自定义属性类,如何在代码中使用它们,以及如何通过反射查询它们。 教程 属性提供功能强大的方法以将声明信息与 C# 代码(类型、方法、属性等)相关联。与程序实体关联后,属性可在运行时查询,并可以以任意多种方式使用。 属性的用法示例包括: 将帮助文档与程序实体关联(通过 Help 属性)。 将值编辑器关联到 GUI 框架中的特定类型(通过 ValueEditor 属性)。 除一个完整的示例外,本教程还包括以下主题: 声明属性类 第一件需要做的事情是声明属性。 使用属性类 创建属性后,随即将属性与特定的程序元素关联。 通过反射访问属性 属性与程序元素关联后,即可使用反射查询属性存在及其值。 声明属性类 在 C# 中声明属性很简单:它采取从 System.Attribute 继承的类声明的形式,并已用 AttributeUsage 属性标记,如下所示:using System; [AttributeUsage(AttributeTargets.All)] public class HelpAttribute : System.Attribute { public readonly string Url; public string Topic // Topic is a named parameter { get { return topic; } set { topic = value; } } public HelpAttribute(string url) // url is a positional parameter { this.Url = url; } private string topic; } 代码讨论 属性 AttributeUsage 指定该属性可以应用于的语言元素。 属性类是从 System.Attribute 派生的公共类,至少有一个公共构造函数。 属性类有两种类型的参数: “定位参数”......

阅读全文(1251) | 评论:0

C# 程序员参考--COM Interop 第二部分:C# 服务器教程(2006-09-03 18:21:00)

摘要:COM Interop 允许 COM 开发人员像访问其他 COM 对象一样轻松访问托管代码。本教程说明如何将 C# 服务器与 C++ COM 客户端一起使用。它还解释了下列活动: 如何创建 C# 服务器 如何创建 COM 客户端 该教程还简要说明了在托管和非托管组件之间自动应用的封送处理。 COM Interop 第一部分:C# 客户端教程显示使用 C# 与 COM 对象交互操作的基础知识,这是该教程的前提。有关两个教程的概述,请参见 COM Interop 教程。 教程 该教程说明下列创建 C# 服务器的活动: 如何使用接口和类上的 Guid 属性将其作为 COM 对象公开以及如何为 Guid 属性生成全局唯一标识符 (GUID)。 如何使用 RegAsm 注册供 COM 客户端使用的 .NET Framework 程序以及从 .NET Framework 程序创建类型库(.tlb 文件)。 该教程还说明下列创建 COM 客户端的活动: 如何导出托管服务器以及如何使用它们创建 COM 对象。 如何将由 RegAsm 生成的 .tlb 文件导入到 COM 客户端,以及如何使用 CoCreateInstance 创建 .NET Framework coclass 的实例。 注意   若要为导出到 COM 客户端的接口和 coclass 创建 GUID,请使用 Guidgen.exe 工具,此工具是作为 Visual Studio 的一部分交付的。Guidgen 使您可以选择 GUID 的表示格式,这样您就不必重新键入它。有关 Guidgen 的更多信息,请参见知识库文章 Q168318“XADM: Guidgen.exe Available Only for Intel Platforms”。知识库文章可以在 MSDN Library 中以及 Web 站点 http://support.microsoft.com 上找到。 示例 本示例由两个文件组成: C# 文件 CSharpServer.cs,它创建 CSharpServer.dll 文件。.dll 用于创建 CSharpServer.tlb 文件。 C++ 文件 COMClient.cpp,它创建可执行客户端 CO......

阅读全文(1382) | 评论:0

C# 程序员参考--COM Interop 第一部分:C# 客户端教程(2006-09-03 18:20:00)

摘要:COM Interop 提供对现有 COM 组件的访问,而不需要修改原始组件。若要将 COM 代码合并到托管应用程序,请通过使用 COM Interop 实用工具 (TlbImp.exe) 导入相关的 COM 类型。一经导入,COM 类型就可以使用。 此外,COM Interop 还使 COM 开发人员能够像访问其他 COM 对象一样轻松访问托管对象。同样,COM Interop 提供了一个专用实用工具 (RegAsm.exe),此工具将托管类型导出到类型库中,并将托管组件注册为传统 COM 组件。 在运行时,公共语言运行库根据需要在 COM 对象和托管对象之间封送数据。 该教程显示如何使用 C# 与 COM 对象交互操作。 COM Interop 第二部分:C# 服务器教程讲述如何将 C# 服务器与 C++ COM 客户端一起使用。有关两个教程的概述,请参见 COM Interop 教程。 教程 C# 使用 .NET Framework 功能执行 COM Interop。C# 支持: 创建 COM 对象。 确定 COM 接口是否由对象实现。 调用 COM 接口上的方法。 实现可由 COM 客户端调用的对象和接口。 .NET Framework 使用 COM Interop 处理引用计数问题,因此不必调用或实现 AddRef 和 Release。 本教程阐述以下主题: 创建 COM 类包装 声明 COM coclass 创建 COM 对象 声明 COM 接口 使用转换而不是 QueryInterface 综述 创建 COM 类包装 要使 C# 代码引用 COM 对象和接口,需要在 C# 内部版本中包含 COM 接口的 .NET Framework 定义。完成此操作的最简单方法是使用 TlbImp.exe(类型库导入程序),它是一个包括在 .NET Framework SDK 中的命令行工具。TlbImp 将 COM 类型库转换为 .NET Framework 元数据,从而有效地创建一个可以从任何托管语言调用的托管包装。用 TlbImp 创建的 .NET Framework 元数据可以通过 /R 编译器选项包括在 C# 内部版本中。如果使用 Visual Studio 开发环境,则只需添加对 CO......

阅读全文(2168) | 评论:0

C# 程序员参考--平台调用教程(2006-09-03 18:19:00)

摘要:平台调用服务 (PInvoke) 允许托管代码调用在 DLL 中实现的非托管函数。 本教程说明使用什么方法才能从 C# 调用非托管 DLL 函数。该教程所讨论的属性允许您调用这些函数并使数据类型得到正确封送。 教程 C# 代码有以下两种可以直接调用非托管代码的方法: 直接调用从 DLL 导出的函数。 调用 COM 对象上的接口方法(有关更多信息,请参见 COM Interop 第一部分:C# 客户端教程)。 对于这两种技术,都必须向 C# 编译器提供非托管函数的声明,并且还可能需要向 C# 编译器提供如何封送与非托管代码之间传递的参数和返回值的说明。 该教程由下列主题组成: 直接从 C# 调用 DLL 导出 默认封送处理和为非托管方法的参数指定自定义封送处理 为用户定义的结构指定自定义封送处理 注册回调方法 该教程包括下列示例: 示例 1 使用 DllImport 示例 2 重写默认封送处理 示例 3 指定自定义封送处理 直接从 C# 调用 DLL 导出 若要声明一个方法使其具有来自 DLL 导出的实现,请执行下列操作: 使用 C# 关键字 static 和 extern 声明方法。 将 DllImport 属性附加到该方法。DllImport 属性允许您指定包含该方法的 DLL 的名称。通常的做法是用与导出的方法相同的名称命名 C# 方法,但也可以对 C# 方法使用不同的名称。 还可以为方法的参数和返回值指定自定义封送处理信息,这将重写 .NET Framework 的默认封送处理。 示例 1 本示例显示如何使用 DllImport 属性通过调用 msvcrt.dll 中的 puts 输出消息。// PInvokeTest.cs using System; using System.Runtime.InteropServices; class PlatformInvokeTest { [DllImport("msvcrt.dll")] public static extern int puts(string c); [DllImport("msvcrt.dll")] internal static extern int _......

阅读全文(1402) | 评论:0

C# 程序员参考--XML 文档教程(2006-09-03 18:18:00)

摘要:本教程展示如何使用 XML 将代码存档。 教程 C# 提供一种机制,供开发人员使用 XML 将其代码存档。在源代码文件中,以下代码行可以作为注释处理并放在文件中:以 /// 开始的行;在用户定义的类型(如类、委托或接口)、某成员(如字段、事件、属性或方法)或某命名空间声明之前的行。 示例 下面的示例提供对某个已存档的类型的基本概述。若要编译该示例,请键入以下命令行:csc XMLsample.cs /doc:XMLsample.xml 这将创建 XML 文件 XMLsample.xml,您可以在浏览器中或使用 TYPE 命令查看该文件。// XMLsample.cs // compile with: /doc:XMLsample.xml using System; /// <summary> /// Class level summary documentation goes here.</summary> /// <remarks> /// Longer comments can be associated with a type or member /// through the remarks tag</remarks> public class SomeClass { /// <summary> /// Store for the name property</summary> private string myName = null; /// <summary> /// The class constructor. </summary> public SomeClass() { // TODO: Add Constructor Logic here } /// <summary> /// Name property </summary> /// <value> /// A value tag is used to describe the property value&......

阅读全文(1206) | 评论:0

C# 程序员参考--条件方法教程(2006-09-03 18:18:00)

摘要:本教程演示条件方法,它们提供一种功能强大的机制,通过它可以根据是否定义了预处理器符号来包括或省略方法调用。 示例文件 请参见“条件方法”示例以下载和生成本教程中讨论的示例文件。 教程 条件方法使开发人员能够创建这样的方法,可将对这些方法的调用放在代码中,然后编译期间根据预处理符号包括或省略这些调用。 假定您想在调试版本中启用某些断言代码,而在发布版本中禁用它们。在 C++ 中,有不止一种方法可以将此功能包含到您的代码中,例如: 使用 #ifdef 同时定义宏的调试版本和发布版本。调试版本调用跟踪代码,而发布版本不执行任何操作。由于 C# 不支持宏,该方法行不通。 具有正在被调用的代码的两个实现。即,在调试版本中,具有完全功能;而在发布版本中,具有方法的空存根 (stub)。然后,用户在链接项目时选择包括哪一个实现。该方法的问题是,发布版本包含对空方法的调用,并且配置较复杂。 C# 条件方法为该问题提供了简单的解决方案,类似于上面列出的第一种方法。该操作有两个基本机制: 直接在源代码中用 #define 定义预处理标识符。 通过 /define 选项 (/d) 在 C# 命令行上定义预处理标识符。下面的示例中使用该方法。 条件方法用于“.NET Framework”中。System.Diagnostics 命名空间包含许多支持应用程序中的跟踪和调试的类。使用 System.Diagnostics.Trace 和 System.Diagnostics.Debug 类向应用程序添加复杂的跟踪和调试(使用条件方法可从发布版本编译掉的功能)。 下面的示例展示如何使用条件方法实现非常简单的跟踪机制。System.Diagnostics.Trace 提供的跟踪机制复杂得多,但它使用下面的基本机制提供该功能。 示例 本示例由两个源文件组成:第一个文件是提供跟踪机制的库,第二个文件是使用该库的客户程序。 文件 #1:创建条件方法 下面的代码展示了一个简单的库,它提供向系统控制台显示跟踪消息的跟踪机制。客户可以将跟踪调用嵌入代码,然后可以通过在自己的编译阶段中定义符号来控制是否调用跟踪。// CondMethod.cs // compile with: /target:library /d:DEBUG using System; ......

阅读全文(1013) | 评论:0

C# 程序员参考--显式接口实现教程(2006-09-03 18:15:00)

摘要:本教程演示如何显式实现接口成员以及如何从接口实例访问这些成员。 教程 实现接口的类可以显式实现该接口的成员。当显式实现某成员时,不能通过类实例访问该成员,而只能通过该接口的实例访问该成员。本教程包含两个示例。第一个示例阐释如何显式实现和访问接口成员。第二个示例展示如何实现具有相同成员名的两个接口。 示例 1 本示例声明一个 IDimensions 接口和一个 Box 类,该类显式实现接口成员 Length 和 Width。通过接口实例 myDimensions 访问这些成员。// explicit1.cs interface IDimensions { float Length(); float Width(); } class Box : IDimensions { float lengthInches; float widthInches; public Box(float length, float width) { lengthInches = length; widthInches = width; } // Explicit interface member implementation: float IDimensions.Length() { return lengthInches; } // Explicit interface member implementation: float IDimensions.Width() { return widthInches; } public static void Main() { // Declare a class instance "myBox": Box myBox = new Box(30.0f, 20.0f); // Declare an interface instance "myDimensions": IDimensions myDimensions = (IDimensions) my......

阅读全文(1028) | 评论:0