【问题标题】:Trying to compile a class using a custom class causes error CS0246尝试使用自定义类编译类会导致错误 CS0246
【发布时间】:2019-12-21 09:47:54
【问题描述】:

我正在努力从命令行编译我的 C# 项目。我做了 2 个简单的类来呈现这个问题。我有一个 Person 类和一个存储 Person 数组的 Registry 类。当我尝试使用 csc 编译注册表文件时,我得到“Registry.cs(4,5): error CS0246: The type or namespace name 'Person' could not be found (are you missing a using directive or an assembly reference?)

一段时间后我发现一个笨拙的解决方法是将Person.cs 文件编译为.dll 文件(使用csc /target:library Person.cs),然后在我尝试编译Registry.cscsc /r:"./Person.dll" /out:test.exe Registry.cs)时引用库文件.这可行,但似乎根本不是正确的工作流程。如果你遇到过类似的情况,请帮忙。下面是这两个类的源代码。

Person.cs

using System;

namespace ClassTest {

public class Person {
    private string Name {set; get;} 
    private int Age {set; get;}

    public Person(string name, int age) {
        Name = name;
        Age = age;
    }

    public void GetInfo() {
        Console.WriteLine("Name: " + Name);
        Console.WriteLine("Age: " + Age + "\n");
    }
}

}

Registry.cs

using System;

namespace ClassTest {

public class Registry {
    Person[] citizens;

    public Registry() {
        citizens = new Person[2];
        citizens[0] = new Person("John", 30);
        citizens[1] = new Person("Mary", 22);
        foreach (Person p in citizens) {
            p.GetInfo();
        }
    }

    public static void Main() {
        Console.WriteLine("");
        Registry r = new Registry();
    }
}

}

【问题讨论】:

  • 我没有看到任何命名空间声明,但我很确定这是强制性的?只有像 SharpLab 这样的东西似乎在本地课程中跳过它们。
  • stackoverflow.com/questions/3750531/… 似乎不是强制性的。
  • 您链接的线程中的每个答案都说明了这件事,您绝对应该拥有一个。很可能这个编译器不够健壮,无法正确理解 Person 的意思是“这个项目的人类”。
  • 将命名空间 ClassTest 添加到 Person.cs 可以消除有关 Person 类的错误。但是,现在我得到了同样的错误,但对于命名空间 ClassTest。 “Registry.cs(4,5):错误 CS0246:找不到类型或命名空间名称“ClassTest”(您是否缺少 using 指令或程序集引用?)”
  • TestClass 必须在同一个命名空间中,或者通过 using 指令使用它。也许“全局”命名空间也可以,但它很丑。

标签: c# visual-studio-code compiler-errors compilation namespaces


【解决方案1】:

我希望我能给你一个更好的答案,但问题似乎归结为你编译不是一个项目,只是一堆松散的 .cs 文件。

编译 Registry.cs 时,编译器不知道 Person.cs 中有什么,因此它无法确定您正在谈论的“Person”类型以及它具有的函数(包括所有重载)、属性和字段。这意味着它无法进行类型检查。更不用说将该类的真实 IL 名称放入代码中,以避免任何混淆。它会停止。

一段时间后我发现一个笨拙的解决方法是将 Person.cs 文件编译为 .dll 文件(使用 csc /target:library Person.cs

这就是它与您引用的所有那些 .NET 库(包括 System.dll)的工作方式。所有这些都已预编译,这就是为什么您可以在没有源代码的情况下使用它们。您现在可以在线查找他们的源代码,但这不是给定的。尤其是对于第 3 方的 .dll,这很少是给定的。

我只能告诉你,当我学习 Native C++ 时,我们是如何做到的。我们使用包含而不是使用。 Wich 实际上更像是添加参考。我们必须在使用该类的每个文件中包含 Person.h。其中包括 Registry.h。但是 IIRC,每个文件也使用 Registry.h。这当然会导致使用 Registry.h 的文件重复,因为它有两个 Person-h - 一个本身,一个来自 Registery.h 的包含。通过预处理器的编译器方式可以解决这个问题,但速度很慢。因此,我们的每个代码文件都以这些预处理器指令开始和结束:

#ifndef CustomIdenfifer
#define CustomIdentifer
//Code
#endif

您可以在整个 Library Sorucefiles 中看到它:https://code.woboq.org/llvm/libcxx/include/string.html

不知何故阻止了相同的包含源代码最终出现两次,同时仍然允许单独编译每个文件。现在 Visual Studio 和 Projecet 文件以某种方式摆脱了手动执行此操作的需要。你没有和他们一起工作,所以你必须手动完成。

至于如何?我不知道为什么。正如我所说,我只是在我以前的 Native C++ 时代才知道这一点。近二十年来,我没有与没有 GUI 的编译器交谈过。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-11
    • 2021-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多