Как "импортировать" статический класс в С#?
Я создал публичный статический класс utils.cs Я хочу использовать его в других классах без метода префикса с utils, что синтаксис для этого?
Ответы
Ответ 1
Что Джон Скайт не говорит вам, что вы можете иметь глобальные статические члены в С#. Ваш класс полезности действительно может стать реальностью в С#.
К сожалению, Microsoft определила, что сам процесс построения таких членов, как и выше, является простым "нормальным" развитием и требует, чтобы вы подделывали их из исходного промежуточного языка. Такой мощный шаблон выше общей подсветки синтаксиса и дружественных значков).
Вот требуемая последовательность символов 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
}
(Вы можете скомпилировать этот пример, вызвав ilasm.exe из командной строки SDK, не забывая использовать переключатель /dll )
выход ilasm.exe:
Microsoft (R).NET Framework IL Assembler. Версия 2.0.50727.4016
Copyright (c) Корпорация Microsoft. Все права защищены.
Сборка 'globalmethods.msil' в DLL → 'globalmethods.dll'
Исходным файлом является ANSI
global.msil(7): предупреждение - ссылка на необъявленную сборку 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);
}
}
}
Да, вы только что назвали глобальный метод в С#.
* Пожалуйста, не используйте это, например, только:-) Кроме того, вы могли бы написать свои глобальные методы на другом языке, который их поддерживает, например, VB.NET.
Ответ 2
В С# нет способа сделать это - нет прямого эквивалента функции статического импорта Java, например.
Для получения дополнительной информации о том, почему это так, см. сообщение Эрика Липперта по теме и аналогичный вопрос SO.
Однако при определенных обстоятельствах может возникнуть смысл писать методы расширения, которые живут в не вложенных статических классах, но "притворяются" экземплярами другого класса. Стоит тщательно подумать, прежде чем вводить их, поскольку они могут ввести в заблуждение, но они также могут улучшить удобочитаемость при разумном использовании.
Какие методы полезности вы думали?
Ответ 3
Как минимум, вы должны указать хотя бы имя класса. Вся используемая директива позволяет вам отказаться от пространства имен. Вы также можете использовать директиву using, чтобы указать псевдоним вместо всего имени namespace.class, но тогда вы должны использовать псевдоним...
using MyClassName = Namespace.MySubNS.OtherNameSpace.OriginalClassname;
MyClassName X = new MyClassName();
Ответ 4
Я предполагаю, что вы могли бы использовать все свои методы в utils.cs в качестве методов расширения для класса объектов, но вам все равно придется префикс ваших методов с помощью "этого". Это, вероятно, не то, что вы хотите.
Ответ 5
В этом потоке есть несколько вопросов и рассуждений о том, что вы не используете глобальные методы, но я хотел бы добавить, что существует еще один вид сценария, когда желателен статический импорт, т.е. когда вы хотите принести некоторые константы в область видимости.
Например, если я хочу построить 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 (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))
Однако я бы предпочел принести константу в область действия без каких-либо повторяющихся, но необходимых имен и точек qualifer вообще (как вы можете сделать с статическим импортом Java), то есть выполните следующее:
DBQuery.Select()
.Field(CustomerID)
.Count(OrderID)
.From(Orders)
.GroupBy(CustomerID)
.OrderBy(CustomerID)
.WhereField(OrderDate, Compare.GreaterThan, DBConst.DateTime(ordersAfter))
Но использовать этот вид синтаксиса с С# нельзя?
Кстати, кто-нибудь знает лучшую библиотеку .NET для создания SQL, чем dynasql, которая, похоже, не предназначена для того, чтобы быть независимой от выполнения SQL (как проблема, описанная здесь: http://dynasql.codeplex.com/Thread/View.aspx?ThreadId=81988)
/Sven
Ответ 6
"Правильный" (с точки зрения OO вхождения члена в область видимости) заключается в том, чтобы выполнить его в рамках области действия:
static class MySpecialStuff
{
public static int MySpecialValue { get {...} }
}
class MyWorkingClass
{
private static int MySpecialValue { get { return ySpecialStuff.MySpecialValue; } }
}
Теперь в оставшейся части MyWorkingClass
(или в производных классах, если вы меняете приватную на защищенную), вы можете ссылаться на MySpecialValue
тысячи раз без каких-либо дополнительных квалификаций.
Ответ 7
Я не уверен, чего вы пытаетесь сделать, опустив префикс Utils
от вызовов метода. Но если это просто для экономии места или для упрощения чтения кода, вы можете добавить его в более короткое имя:
using U = Utils;
Ответ 8
Я никогда не интересовался концепцией "глобального метода". Кроме того, похоже, что он делает гораздо более удобочитаемый/поддерживаемый код, чтобы не иметь классов под названием "Util", которые содержат вспомогательные методы любого типа. Вместо этого что-то вроде MathLib, который, по крайней мере, документирует, какой метод работает.
В случае с финансовой библиотекой я мог бы видеть ее там, где вы, возможно, не захотите всегда делать MathLib.Sum() или что-то еще. Может быть, вы можете ввести перегрузку оператора в свои типы, чтобы вы могли выполнять вычисления на них с более упрощенным синтаксисом при манипулировании бизнесом своих бизнес-объектов?
Я могу немного пристрастеть (сердито) после прочтения кода VB6 за последние несколько недель, когда глобальные методы повсюду. Сказано, что это всего лишь мои два цента:)
Ответ 9
С С# 6 теперь вы можете использовать статический импорт (см. msdn) Например,
using static Utils;