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

时间:2009-09-14 20:42:31

标签: c#

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

9 个答案:

答案 0 :(得分:27)

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

有关为何会出现这种情况的详细信息,请参阅主题Eric Lippert's postsimilar SO question

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

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

答案 1 :(得分:14)

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();

        }

    }

    /// <summary>
    /// Reduces the amount of code for global call
    /// </summary>
    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。

答案 2 :(得分:4)

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

using MyClassName = Namespace.MySubNS.OtherNameSpace.OriginalClassname;

MyClassName X = new MyClassName(); 

答案 3 :(得分:1)

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

答案 4 :(得分:1)

在这个帖子中有一些关于不使用全局方法的质疑和论证,但我想补充说,当需要静态导入时,即当你想将一些常量带入范围时,还有另一种情况。 例如,如果我想构造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)  ?

/ Sven

答案 5 :(得分:1)

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

static class MySpecialStuff 
{
    public static int MySpecialValue { get {...} }
}

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

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

答案 6 :(得分:0)

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

using U = Utils;

答案 7 :(得分:0)

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

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

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

答案 8 :(得分:0)

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

using static Utils;