Как создать псевдоним имени класса в C #, не добавляя строку кода в каждый файл, который использует класс? - PullRequest
65 голосов
/ 28 октября 2008

Я хочу создать псевдоним для имени класса. Следующий синтаксис был бы идеальным:

public class LongClassNameOrOneThatContainsVersionsOrDomainSpecificName
{
   ...
}

public class MyName = LongClassNameOrOneThatContainsVersionOrDomainSpecificName;

но он не скомпилируется.


Пример

Примечание Этот пример предназначен только для удобства. Не пытайтесь решить эту конкретную проблему, предлагая изменить дизайн всей системы. Наличие или отсутствие этого примера не меняет первоначальный вопрос.

Некоторый существующий код зависит от наличия статического класса:

public static class ColorScheme
{
   ...
}

Эта цветовая схема является цветовой схемой Outlook 2003. я хочу представить цветовую схему Outlook 2007, сохранив цветовую схему Outlook 2003:

public static class Outlook2003ColorScheme
{
   ...
}

public static class Outlook2007ColorScheme
{
   ...
}

Но я все еще сталкиваюсь с тем фактом, что код зависит от наличия статического класса с именем ColorScheme. Моей первой мыслью было создание класса ColorScheme, который я буду наследовать из Outlook2003 или Outlook2007:

public static class ColorScheme : Outlook2007ColorScheme
{
}

но вы не можете выйти из статического класса.

Моей следующей мыслью было создать статический класс ColorScheme, но сделать классы Outlook2003ColorScheme и Outlook2007ColorScheme нестатическими. Тогда статическая переменная в статическом классе ColorScheme может указывать на «истинную» цветовую схему:

public static class ColorScheme
{
    private static CustomColorScheme = new Outlook2007ColorScheme();
    ...
}

private class CustomColorScheme 
{ 
   ...
}

private class Outlook2008ColorScheme : CustomColorScheme 
{
    ...
}

private class Outlook2003ColorScheme : CustomColorScheme 
{
   ...
}

но это потребовало бы, чтобы я преобразовал класс, составленный полностью из статически доступных только для чтения цветов, в переопределяемые свойства, и тогда мой класс ColorScheme должен был бы иметь 30 различных методов получения свойств, которые были бы объединены в содержащийся объект.

Это слишком много печатать.

Так что моей следующей мыслью было псевдоним класса:

public static ColorScheme = Outlook2007ColorScheme;

Но это не компилируется.

Как создать псевдоним статического класса для другого имени?


Обновление: Может кто-нибудь добавить ответ "Вы не можете сделать это в C #" , поэтому я могу пометить это как принятый ответ. Любой, кто хочет получить ответ на тот же вопрос, найдет этот вопрос, принятый ответ и ряд обходных путей, которые могут или не могут быть полезны.

Я просто хочу закрыть этот вопрос.

Ответы [ 10 ]

110 голосов
/ 28 октября 2008

Если вы измените исходное имя класса, вы можете переписать зависимый код, используя псевдоним импорта в качестве замены typedef:

using ColorScheme = The.Fully.Qualified.Namespace.Outlook2007ColorScheme;

Это должно идти в верхней части файла / пространства имен, как и обычные using s.

Я не знаю, насколько это практично в вашем случае.

21 голосов
/ 28 октября 2008

Вы можете создать псевдоним для своего класса, добавив следующую строку кода:

using Outlook2007ColorScheme = YourNameSpace.ColorScheme;
12 голосов
/ 28 октября 2008

Вы хотите ( Factory | Singleton ), в зависимости от ваших требований. Идея заключается в том, чтобы клиентский код не знал, какую цветовую схему он получает. Если цветовая схема должна иметь широкое применение, синглтон должен подойти. Если вы можете использовать другую схему в разных обстоятельствах, возможно, вам подойдет шаблон Factory. В любом случае, когда необходимо изменить цветовую схему, код нужно менять только в одном месте.

public interface ColorScheme {
    Color TitleBar { get; }
    Color Background{ get; }
    ...
}

public static class ColorSchemeFactory {

    private static ColorScheme scheme = new Outlook2007ColorScheme();

    public static ColorScheme GetColorScheme() { //Add applicable arguments
        return scheme;
    }
}

public class Outlook2003ColorScheme: ColorScheme {
   public Color TitleBar {
       get { return Color.LightBlue; }
   }

    public Color Background {
        get { return Color.Gray; }
    }
}

public class Outlook2007ColorScheme: ColorScheme {
   public Color TitleBar {
       get { return Color.Blue; }
   }

    public Color Background {
        get { return Color.White; }
    }
}
11 голосов
/ 12 января 2009

Вы не можете использовать псевдоним класса в C #.

Есть вещи, которые вы можете сделать, которые не налагают имя класса в C #.

Но чтобы ответить на оригинальный вопрос: вы не можете использовать псевдоним класса в C #.


Обновление: Люди смущены, почему using не работает. Пример:

Form1.cs

private void button1_Click(object sender, EventArgs e)
{
   this.BackColor = ColorScheme.ApplyColorScheme(this.BackColor);
}

ColorScheme.cs

class ColorScheme
{
    public static Color ApplyColorScheme(Color c) { ... }
}

И все работает. Теперь я хочу создать новый класс и псевдоним ColorScheme для него (так что нет необходимости изменять код ):

ColorScheme.cs

using ColorScheme = Outlook2007ColorScheme;

class Outlook2007ColorScheme
{
    public static Color ApplyColorScheme(Color c) { ... }
}

О, прости. Этот код не компилируется:

enter image description here

Мой вопрос был о том, как псевдоним класс в C #. Это не может быть сделано. Есть вещи, которые я могу сделать, это , а не наложение имени класса в C #:

  • изменить всех, кто зависит от ColorScheme на using ColorScheme вместо этого (обходной путь изменения кода, потому что я не могу назвать псевдоним)
  • Измените всех, кто зависит от ColorScheme, на использование фабричного шаблона их полиморфного класса или интерфейса (обходной путь изменения кода, потому что я не могу назвать псевдоним)

Но эти обходные пути включают взлом существующего кода: не вариант.

Если люди зависят от присутствия ColorScheme класса, я должен скопировать / вставить класс ColorScheme.

Другими словами: я не могу назвать псевдоним класса в C #.

Это отличается от других объектно-ориентированных языков, где я мог бы определить псевдоним:

ColorScheme = Outlook2007ColorScheme

и я бы сделал.

10 голосов
/ 28 октября 2008

попробуйте это:

using ColorScheme=[fully qualified].Outlook2007ColorScheme
4 голосов
/ 21 ноября 2017

Я добавляю этот комментарий для пользователей, которые находят это задолго до того, как OP принял их «ответ». Псевдоним в C # работает путем указания имени класса, используя его полностью определенное пространство имен. Определенный, псевдоним может быть использован в его области видимости. Пример.

using aliasClass = Fully.Qualified.Namespace.Example;
//Example being the class in the Fully.Qualified.Namespace

public class Test{

  public void Test_Function(){

    aliasClass.DoStuff();
    //aliasClass here representing the Example class thus aliasing
    //aliasClass will be in scope for all code in my Test.cs file
  }

}

Извиняюсь за быстро набранный код, но, надеюсь, он объясняет, как это должно быть реализовано, чтобы пользователи не вводили в заблуждение, полагая, что это не может быть сделано в C #.

3 голосов
/ 26 июня 2015

Полагаю, вы всегда можете наследовать от базового класса, не добавляя ничего

public class Child : MyReallyReallyLongNamedClass {}

UPDATE

Но если у вас есть возможность рефакторинга самого class: имя класса обычно излишне длинное из-за отсутствия namespace s.

Если вы видите случаи как ApiLoginUser, DataBaseUser, WebPortalLoginUser, это обычно указывает на отсутствие namespace из-за страха, что имя User может конфликтовать.

В этом случае, однако, вы можете использовать namespace псевдоним , как было указано выше в постах

using LoginApi = MyCompany.Api.Login;
using AuthDB = MyCompany.DataBase.Auth;
using ViewModels = MyCompany.BananasPortal.Models;

// ...
AuthDB.User dbUser;
using ( var ctxt = new AuthDB.AuthContext() )
{
    dbUser = ctxt.Users.Find(userId);
}

var apiUser = new LoginApi.Models.User {
        Username = dbUser.EmailAddess,
        Password = "*****"
    };

LoginApi.UserSession apiUserSession = await LoginApi.Login(apiUser);
var vm = new ViewModels.User(apiUserSession.User.Details);
return View(vm);

Обратите внимание, что имена class все User, но в разных namespace с. Цитата PEP-20: Zen of Python :

Пространства имен - одна из отличных идей - давайте сделаем больше таких!

Надеюсь, это поможет

3 голосов
/ 01 марта 2015

Псевдоним, который вы хотели бы сделать, не будет работать в C #. Это связано с тем, что псевдонимы выполняются с помощью директивы using, которая ограничена рассматриваемым файлом / пространством имен. Если у вас есть 50 файлов, которые используют старое имя класса, это будет означать 50 мест для обновления.

Тем не менее, я думаю, что есть простое решение, чтобы сделать ваш код минимально возможным. Сделайте класс ColorScheme фасадом для ваших обращений к реальным классам с помощью реализации и используйте using в этом файле, чтобы определить, какой ColorScheme вы используете.

Другими словами, сделайте это:

using CurrentColorScheme = Outlook2007ColorScheme;
public static class ColorScheme
{
   public static Color ApplyColorScheme(Color c)
   {
       return CurrentColorScheme.ApplyColorScheme(c);
   }
   public static Something DoSomethingElse(Param a, Param b)
   {
       return CurrentColorScheme.DoSomethingElse(a, b);
   }
}

Тогда в вашем коде ничего не измените:

private void button1_Click(object sender, EventArgs e)
{
   this.BackColor = ColorScheme.ApplyColorScheme(this.BackColor);
}

Затем можно обновить значения ColorScheme, обновив одну строку кода (using CurrentColorScheme = Outlook2008ColorScheme;).

Пара касается здесь:

  • Каждый новый метод или определение свойства необходимо будет добавить в двух местах: к классу ColorScheme и к классу Outlook2007ColorScheme. Это дополнительная работа, но если это настоящий устаревший код, это не должно быть частым случаем. В качестве бонуса, код в ColorScheme настолько прост, что любая возможная ошибка очень очевидна.
  • Такое использование статических классов не кажется мне естественным; Я, вероятно, попытался бы реорганизовать унаследованный код, чтобы сделать это по-другому, но я также понимаю, что ваша ситуация может этого не допустить.
  • Если у вас уже есть класс ColorScheme, который вы заменяете, этот подход и любой другой может стать проблемой. Я бы посоветовал вам переименовать этот класс в что-то вроде ColorSchemeOld, а затем получить к нему доступ через using CurrentColorScheme = ColorSchemeOld;.
2 голосов
/ 28 октября 2008

Можно ли перейти на использование интерфейса?

Возможно, вы могли бы создать IColorScheme интерфейс, который реализуют все классы?

Это будет хорошо работать с заводским шаблоном, как показано Крисом Марасти-Георгом

0 голосов
/ 31 августа 2015

Это очень поздний частичный ответ - но если вы определяете тот же класс 'ColorScheme' в том же пространстве имен 'Outlook', но в отдельных сборках, одна из которых называется Outlook2003, а другая - Outlook2007, то все, что вам нужно сделать, это справочная информация соответствующая сборка.

...