C#中的#include指令

有替代品吗? 如果有,指令将如何查找名为“class.cs”的文件? 我只想将代码拆分为每个类的文件。

不,#include语句没有替代品。 C#是一种面向对象的语言,其中代码被组织成类。 您可以根据其可见性使用另一个类中的一个类的代码,并且可以使用分部类将代码从单个类拆分为多个源文件。 这些基本上就是你在另一个“文件”中使用代码的方式。 但它根本不是一回事。

在C#(超出generics)中实现元编程的惯用方法是使用T4模板 – Visual Studio和MSBuild支持T4内置,但是VS没有T4语法着色 – 你需要一个第三方加载项。

为了演示T4的includefunction,我将使用想要在不使用inheritance的情况下同时向多个类添加==运算符重载的场景。

为了比较,在C ++中它将是这样的:

OperatorEquals.inc

 bool operator==(const TYPE* lhs, const TYPE* rhs) { if( lhs == nullptr && rhs != nullptr ) return false; return lhs.Equals(rhs); } 

Code.h

 class Foo { public: #define TYPE Foo #include "OperatorEquals.inc" } class Bar { public: #define TYPE Bar #include "OperatorEquals.inc" } 

在C#中,你会这样做:

  1. 使用partial类,以便所有非元编程逻辑(即普通的C#代码)都在一个文件中,例如Foo.csBar.cs
  2. 在项目中创建一个新的T4模板,将输出文件扩展名更改为.cs
  3. 在该T4( *.tt )文件中创建相同类型的第二个partial class定义,但您不会使用C#语法突出显示。
  4. 定义包含的文件:

Operators.inc.cs.t4

 public static operator==(<#= typeName #> x, <#= typeName #> y) { if( x == null && y != null ) return false; return x.Equals( y ); } 
  1. 将其添加到您的T4模板:

Metaprogramming.tt

 <#@ template debug="false" hostspecific="false" language="C#" #> <#@ import namespace="System" #> <#@ output extension=".cs" #> <# String typeName = null; #> public partial class Foo { <# typeName = "Foo"; #> <#@ include file="Operators.inc.cs.t4" #> } public partial class Bar { <# typeName = "Bar"; #> <#@ include file="Operators.inc.cs.t4" #> } 

每当你“保存” .tt文件时(即使你没有做任何更改),VS将重新生成输出.cs文件,如下所示:

 public partial class Foo { public static operator==(Foo x, Foo y) { if( x == null && y != null ) return false; return x.Equals( y ); } } public partial class Bar { public static operator==(Bar x, Bar y) { if( x == null && y != null ) return false; return x.Equals( y ); } } 

请注意,这种情况是设计的 – 如果你确实想要添加operator== (以及所有其他operator==IEquatableoperator!=IComparable等),那么你可能会使用T4渲染函数代替包含,因为这使参数化更直接,并将所有内容保持在一个文件中:

T4RenderFunction.tt

 <#@ template debug="false" hostspecific="false" language="C#" #> <#@ import namespace="System" #> <#@ output extension=".cs" #> <# String typeName = null; #> public partial class Foo { <# RenderBoilerplateOperators("Foo"); #> } public partial class Bar { <# RenderBoilerplateOperators("Bar"); #> } <#+ // Functions are declared at the bottom void RenderBoilerplateOperators(String typeName) { #> public static operator==(<#= typeName #> lhs, <#= typeName #> rhs) { return <#= typeName #>.Equals( lhs, rhs ); } public override Boolean Equals(<#= typeName #> other) { return <#= typeName #>.Equals( this, other ); } public static Boolean Equals(<#= typeName #> lhs, <#= typeName #> rhs) { // T4 can use VS DTE to enumerate members of `typeName`, but you're probably better-off implementing this method manually } public static operator!=(<#= typeName #> lhs, <#= typeName #> rhs) { return !<#= typeName #>.Equals( lhs, rhs ); } // and so on... <# } // void RenderBoilerplateOperators #> 

另外,不要忘记C# partial类具有一些您可能通过#include语句获得的function。

部分类允许您将类定义拆分为多个文件。

与C#中的C或C ++不同,不需要#include来使用其他文件中定义的类型。 相反,C#基于容器(如类或命名空间)进行类型解析。 只要两个文件都包含在编译中并且第二种类型的命名空间可用,那么您的类就可以访问。

例:

将Class1.cs

 namespace Project1 { class Class1 { ... } } 

Class2.cs

 namespace Project1 { class Class2 { private Class1 m_field1; .. } } 

有点不清楚你的意思。 但是你在考虑:

 using MyNamespace; 

查看使用声明

如果使用msbuild或在csc(C#Compiler)命令行中,则将每个文件包含在* .csproj中:

 csc File1.cs File2.cs 

http://msdn.microsoft.com/en-us/library/78f4aasd%28VS.80%29.aspx

它与C的#include指令不完全相同,但C#的using语句就是你所追求的:

 using Assembly.Name; 

它在命名空间级别而不是文件级别工作。 因此,如果class.csApplication.Core命名空间中包含一个名为SomeClass的公共类,则它看起来像:

 using Application.Core; 

这通常放在您正在使用的文件的顶部,并允许该类使用SomeClass作为对象(以及Application.Core命名空间中的所有其他公共类)。

当然,如果类都在同一个命名空间(例如Application.Core ),那么根本就没有理由使用using语句。 同一名称空间中的类可以在没有任何声明的情况下相互解析。

您需要将class.cs的内容放入命名空间。 然后在需要查看class.cs的文件顶部放置一个using语句。

 class.cs namespace Class { //class.cs stuff } 

然后在需要类的文件中执行以下操作。

  using Class; 

使用Partial Class的示例。

Main.cs

 partial class Program { private static void Main() { A(); B(); } } 

fileA.cs

 partial class Program { private static void A() => Console.WriteLine("A"); } 

fileB.cs

 partial class Program { private static void B() => Console.WriteLine("B"); }