如何在C#中“导入”静态类?

我创建了一个公共静态类utils.cs我想在其他类中使用它而不用带有utils的前缀方法,这样做的语法是什么?

Jon Skeet没有告诉你的是你可以在c#中拥有全局静态成员。 您的实用程序类确实可以在c#中成为现实。

不幸的是,微软已经确定构建上述成员的过程仅仅是“正常”开发,并且要求您使用原始中间语言来构建它们。 这种强大的模式高于常见的语法高亮和友好的图标)。

这是utf-8字符的必要序列(谨慎保护):

.assembly globalmethods {} .method static public void MyUtilMethod() il managed { ldstr "Behold, a global method!" call void [mscorlib]System.Console::WriteLine(class System.String) ret } 

(您可以通过从SDK命令提示符调用ilasm.exe来编译此示例,记住使用/ dll开关)


ilasm.exe输出:

Microsoft(R).NET Framework IL汇编程序。 版本2.0.50727.4016版权所有(c)Microsoft Corporation。 版权所有。 将’globalmethods.msil’汇编到DLL – >’globalmethods.dll’源文件是ANSI

global.msil(7):warning – 对未声明的extern程序集’mscorlib’的引用。 尝试自动检测

汇编的全局方法MyUtilMethod

创建PE文件

发送课程:

发射场和方法:全球方法:1;

发送事件和属性:全局写入PE文件操作已成功完成


编译完新创建的程序集后(例如“globalmethods.dll”),只需在Visual Studio中添加引用即可。 当这完成后,你最好坐下来,因为是时候写一些真正的代码了:

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; namespace TestGlobalMethod { class Program { static void Main(string[] args) { "MyUtilMethod".Call(); Console.ReadKey(); } } ///  /// Reduces the amount of code for global call ///  public static class GlobalExtensionMethods { public static void Call(this string GlobalMethodName) { Assembly.Load("globalmethods") .GetLoadedModules()[0].GetMethod(GlobalMethodName) .Invoke(null,null); } } } 

是的,你刚刚在c#中调用了一个Global方法。

*请不要使用它,仅作为示例:-)另外,您可以用另一种支持它们的语言编写全局方法,例如VB.NET。

例如,在C#中无法做到这一点 – 没有直接相当于Java的静态导入function。

有关这种情况的详细信息,请参阅Eric Lippert关于该主题的post以及类似的SO问题 。

但是,在某些情况下,编写扩展方法可能是有意义的,这些扩展方法存在于非嵌套静态类中,但“假装”为不同类的实例方法。 在介绍这些之前,值得仔细思考,因为它们可能令人困惑 – 但是当明智地使用它们时,它们也可以提高可读性。

你在想什么样的实用方法?

至少,您必须至少指定类名。 所有using指令都允许您不使用命名空间。 您还可以使用using指令来指定别名而不是整个namespace.class名称,但是您必须使用别名…

 using MyClassName = Namespace.MySubNS.OtherNameSpace.OriginalClassname; MyClassName X = new MyClassName(); 

我想你可以把utils.cs中的所有方法都作为对象类的扩展方法,但你仍然必须在方法前加上“this。”,这可能不是你想要的。

在这个post中有一些关于不使用全局方法的质疑和论证,但我想补充一点,当需要静态导入时,还有另一种情况,即当你想将一些常量带入范围时。 例如,如果我想构造SQL语句,我宁愿不使用重复的字符串文字,如在此代码示例中(使用dynasql):

  DBQuery.Select() .Field("CustomerID") .Count("OrderID") .From("Orders") .GroupBy("CustomerID") .OrderBy("CustomerID") .WhereField("OrderDate", Compare.GreaterThan, DBConst.DateTime(ordersAfter)) 

我更喜欢这样做:

  public class OrderTable { public const string Orders = "Orders"; public const string CustomerID = "CustomerID"; public const string OrderID = "OrderID"; public const string OrderDate = "OrderDate"; } ... DBQuery.Select() .Field(OrderTable.CustomerID) .Count(OrderTable.OrderID) .From(OrderTable.Orders) .GroupBy(OrderTable.CustomerID) .OrderBy(OrderTable.CustomerID) .WhereField(OrderTable.OrderDate, Compare.GreaterThan, DBConst.DateTime(ordersAfter)) 

如果我将使用Loadmaster的建议(10月16日16:49),那么我可以这样做:

  using O = TestingDynasql.OrderTable; ... DBQuery.Select() .Field(O.CustomerID) .Count(O.OrderID) .From(O.Orders) .GroupBy(O.CustomerID) .OrderBy(O.CustomerID) .WhereField(O.OrderDate, Compare.GreaterThan, DBConst.DateTime(ordersAfter)) 

但是,我更愿意将常量带入范围,而不需要任何重复但需要的名称和点限定符(就像您可以使用Java的静态导入一样),即执行此操作:

  DBQuery.Select() .Field(CustomerID) .Count(OrderID) .From(Orders) .GroupBy(CustomerID) .OrderBy(CustomerID) .WhereField(OrderDate, Compare.GreaterThan, DBConst.DateTime(ordersAfter)) 

但是不可能在C#中使用这种语法?

顺便说一下,有没有人知道用于创建SQL的更好的.NET库而不是dynasql,它似乎并不是为了独立于SQL执行而设计的(如下所述: http : //dynasql.codeplex.com/ Thread / View.aspx?ThreadId = 81988 )?

/斯文

“适当的”(从OO的角度来看,将成员纳入范围,是在范围内实施它:

 static class MySpecialStuff { public static int MySpecialValue { get {...} } } class MyWorkingClass { private static int MySpecialValue { get { return ySpecialStuff.MySpecialValue; } } } 

现在在MyWorkingClass的其余部分(或者在派生类中,如果将private更改为protected),您可以在没有任何其他资格的情况下数千次引用MySpecialValue

通过省略方法调用中的Utils前缀,我不确定你要完成什么。 但是,如果只是为了节省空间或使代码更容易阅读,您可以将导入别名为更短的名称:

 using U = Utils; 

我从未真正关心过“全球方法”的概念。 此外,似乎它使得更具可读性/可维护性的代码不具有包含任何类型的辅助方法的称为“Util”的类。 而是像MathLib这样的东西,它至少记录了正在操作的方法。

在金融图书馆的情况下,我可以看到你可能不想总是要做MathLib.Sum()或其他什么。 也许您可以将操作符重载引入您的类型,以便在操作业务对象时可以使用更简化的语法对它们执行计算?

在过去几周阅读VB6代码之后,我可能会有点偏颇(脾气暴躁)。 据说这只是我的两分钱:)

使用C#6,您现在可以使用静态导入(参见msdn )例如,

 using static Utils;