【问题标题】:Relation between DLLs and Namespaces in C#C# 中 DLL 和命名空间之间的关系
【发布时间】:2013-11-18 19:59:58
【问题描述】:

这里是高级问题:

我今天花了很多时间自学基本的高级概念,例如 API、静态和动态库、DLL 和 C# 中的编组。获得所有这些知识使我想到了一个看似非常基本的问题,并且可能表明我对这些概念的理解存在漏洞:

我所知道的:

  • DLL 可能包含类,而这些类又包含各种类成员,例如方法和字段,其中一些我可能希望在我的程序中使用
  • 在 C# 中,我们在代码顶部使用关键字“using”来定义我们的命名空间 想加入我们的计划

我没有得到什么:

我的印象是实际的方法是在 DLL 中定义的。当我给它们的只是一个命名空间时,我的程序如何找到在 DLL 中定义的实际函数?对我来说,在顶部使用“使用 XYZ.dll”而不是“使用 XYZ_namespace”似乎更直观。

非常感谢您帮助我填补这里的空白。

编辑:将帖子修改为特定于 C#。

编辑 2:对于其他想知道他们的 C# 应用程序如何真正获得通过“使用 namespaceX”提供的类型的人来说,这是一个很好的资源(除了下面的有用帖子):@987654321 @

基本上,您要使用的类型位于库中,您必须将 Visual Studio 设置为引用这些库,以便在您的代码中“使用”其命名空间。

【问题讨论】:

  • C#:dll 或 exe 是一个程序集。一个程序集可以在任意数量的命名空间中具有内部类和函数供其使用(内部限制对同一程序集的访问)。命名空间是包含类的内容,也是您处理它们的方式。程序集引用是基于每个项目的,而命名空间引用是每个文件的。
  • 这个问题到处都是。命名空间与 DLL。包括与使用。如何在 C++ 与 C# 中定义方法。程序集与 DLL。一般而言,C++(托管和非托管)与 C# 之间存在许多差异。似乎有很多答案和详细说明。投票结束。我建议您一次只专注于一种语言。
  • @P.Brian.Mackey 如果不清楚,我会将我的帖子修改为特定于 C#。不过,对于其他一些语言,这个问题仍然是一样的。使用 C# 语法:当我想要掌握的方法实际上驻留在 DLL 中时,“使用”命名空间有何意义。

标签: c# .net dll


【解决方案1】:

DLL 包含许多我们可能希望在我们的 程序

部分正确。 .Net DLL 包含 Classes,而这些类包含 Members(字段、常量、方法、属性、事件、运算符、索引器)。

.Net 是严格的 OOP,它不允许代码“漂浮在边缘”。一切都在类中定义。

类在Namespaces 中组织只是为了保持命名分离和组织。将命名空间视为包含一个或多个类的“文件夹”,并且可能在一个或多个程序集 (DLL) 中定义。

例如,System 命名空间内的类在 2 个程序集 (DLL) 中定义:mscorlib.dllSystem.dll

同时,这两个程序集包含许多不同的命名空间,因此您可以将程序集与命名空间的关系视为多对多。

当您将 using 指令放在 C# 代码文件的开头时,您是在告诉编译器 “我想使用在此定义的类 Namespace, 不不管他们来自哪个大会”。您将能够在当前项目的所有程序集Referenced 中使用此类命名空间中定义的所有类。

【讨论】:

  • 谢谢,这很有帮助。我有点难以理解 System 命名空间是在 2 个程序集 (DLL) 中定义的。我认为 DLL 文件是最外层的存储桶。然后里面是几个命名空间,这些命名空间又包含几个类。这不对吗?系统命名空间是否跨多个 DLL 文件复制?再次感谢。
  • @user3006096 是和否。 Tim S.'s comment 完美地解释了这一点。
  • 非常感谢 HighCore。除此之外,您的帖子帮助我理解了最初让我感到困惑的多对多关系。
  • 对不起,如果我在这里使用了错误的评论部分,但只是最后一个问题:为什么在几个程序集/DLL 中指定了系统命名空间?在一个文件中拥有完整的命名空间还不够吗?或者他们是否希望在不同的 DLL 文件中有不同的方法,但同时在同一个命名空间中,因为它们有点属于同一类?再次感谢
  • @user3006096 你为什么一直在谈论方法?同样,方法属于一个类,它们不能存在于类定义之外。是的,它们将不同的 classes 放在同一个命名空间中,即使它们可能定义在不同的程序集中,因为它们属于一起。
【解决方案2】:

在 C# 中,DLL(也称为程序集)包含 classes(和其他类型)。这些类型通常有很长的全名,例如System.Collections.Generic.List<T>。这些类型可以包含方法。

在您的References 区域中,您有对程序集的引用(这是您的 .csproj 文件的一部分)。在 .cs 文件中,您无需包含任何 using 即可引用此 DLL,因为它已在您的 .csproj 文件中引用。

如果您包含像 using System.Collections.Generic; 这样的行,它会告诉 C# 编译器在您键入 List<T> 时查找 System.Collections.Generic.List<T>。但是,您不需要这样做:您只需输入 System.Collections.Generic.List<T>

【讨论】:

  • DLL 不包含命名空间吗?即使您不声明一个,也只是将类添加到全局命名空间 iirc。类和结构是层次结构中的一个级别。
  • @AlexBeisley 是的,也不是。 “命名空间”在任何意义上都不是真正的结构,它只是一个逻辑分组。该程序集没有声明它包含System.Collections.Generic 命名空间的任何地方,它只包含System.Collections.Generic.List<T> 类型。
  • @TimS。那么,在引用中我指定了我的代码应该使用的 DLL,然后我可以使用这些 DLL 中命名空间中的方法吗?反正有没有在 Visual Studio 中看到这个参考区域(以防我想添加其他 DLL,默认情况下不添加)?
  • 是的,在解决方案资源管理器中,在您的项目下,它是一个类似文件夹的项目。请参阅iprodeveloper.com/content/content/65330/references_f01.jpg 获取图片
  • @TimS。啊,太棒了,我在参考列表中看到 CSharp.dll、System.dll 和其他一些。它不包括 mscorlib.dll,但我想这没关系,因为我需要的所有类型都包含在当前引用的 DLL 的命名空间中。
【解决方案3】:

我的印象是实际的方法是在 DLL。我的程序如何找到定义的实际函数 在 DLL 中,当我给它们的只是一个命名空间时?

通过静态或动态绑定以及程序集binding 来查找正确代码的过程。当你编译代码时,静态绑定会告诉你是否写了错误的代码或忘记添加引用:

ClassInADifferentAssembly.M(); //通常这将静态绑定和 如果您忘记包含对的引用,则会导致编译器错误 DifferentAssembly

除非你正在处理dynamic 或反射,否则你有静态绑定。程序集绑定是一个不同的过程。整个过程是complex,但基本上程序集是在 GAC 中发现的,当前位置,或者您甚至可以自己处理事件,AppDomain.AssemblyLoad

因此,当您添加using statement 时,静态绑定可以成功地在上下文中找到正确的代码。但是,如果以后程序集在运行时绑定失败,您仍然会收到运行时错误。

【讨论】:

  • 这是非常有用的信息。所以一步一步(以 List 为例): 1)我编译我的程序(其中包含“List list = ...”以及顶部的“using System.Collections.Generic”)。 2) 编译器查看我的引用列表中的所有 DLL,并将它们静态绑定到我的程序。 3) 编译器在所有绑定的 DLL 中搜索 System.Collections.Generic 命名空间。 4)一旦找到它,一切都很好。对吗?
  • 我提醒关注静态绑定的方式。编译器如何执行一个过程会很快导致实现细节。在 C# 的未来版本或 CLR 的其他实现中,可能不会遵循相同的实现。重要的是要将静态绑定和程序集绑定识别为两个不同的过程,并且不要混淆两者。
【解决方案4】:

DLL 是动态链接库的缩写。并且可以是一个包含类、方法等的类库,它们都可以放在不同的命名空间下。

因此,首先您必须在项目中添加对 DLL 的引用。完成后,您可以使用诸如“using”之类的关键字来基本上缩短到达该特定命名空间中的方法/类的路径。

示例命名空间

Namespace.Something.SomethingMore.Finally.Just.One.More
Namespace.Something.SomethingMore.Finally.Just.One.More2

要访问这些命名空间下的类,您可以执行以下任一操作

using Namespace.Something.SomethingMore.Finally.Just.One.More;
using Namespace.Something.SomethingMore.Finally.Just.One.More2;

// Now you can access classes under those namespaces without typing the whole namespace
// Like in the row below
Class.GetData();

如果您没有 usings,您仍然可以访问这些类。但随后必须输入

Namespace.Something.SomethingMore.Finally.Just.One.More.Class.GetData();
Namespace.Something.SomethingMore.Finally.Just.One.More2.AnotherClass.GetData();

【讨论】:

    【解决方案5】:

    DLL 具有一组函数。 您可以通过以下两种方式之一调用这些函数: 链接到 DLL 导出库(一个 lib 文件)或在运行时进行链接: 调用 LoadLibrary() 调用 GetProcAddress 并提供所需函数的名称。您需要将其转换为实际类型(函数指针)。 通过新的函数指针调用函数。 非常简单的东西,只需在 MSDN 上阅读即可。 C++ 命名空间只是函数名的一部分。 您可以使用名为 Dependency Walker 的工具查看从 DLL 导出的函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-16
      • 2014-11-16
      • 1970-01-01
      • 2015-06-10
      • 1970-01-01
      • 2010-09-23
      • 2020-08-21
      • 1970-01-01
      相关资源
      最近更新 更多