我已经创建了一个公共静态类utils.cs我想在其他类中使用它而不用带有utils的前缀方法,这样做的语法是什么?
答案 0 :(得分:27)
在C#中无法做到这一点 - 例如,没有直接相当于Java的静态导入功能。
有关为何会出现这种情况的详细信息,请参阅主题Eric Lippert's post和similar 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'的引用。 尝试自动检测
创建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;