Як встановити псевдонім назви класу в C #, не додаючи рядок коду до кожного файлу, що використовує клас?


87

Я хочу створити псевдонім для імені класу. Наступний синтаксис буде ідеальним:

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 #" , щоб я міг позначити це як прийняту відповідь. Будь-хто, хто хоче отримати відповідь на те саме питання, знайде це питання, прийняту відповідь та низку обхідних шляхів, які можуть бути, а можуть і не бути корисними.

Я просто хочу закрити це питання.


ви можете прийняти відповідь Кріса, навіть якщо ви не хочете її реалізовувати
devio,

2
Це не відповідь, це обхідний шлях. Відповідь полягає в тому, що ви не можете - принаймні, поки хтось не з’явиться і не опублікує фактичний синтаксис для цього.
Ян Бойд

1
Для тих, хто приходить сюди, прийнята відповідь є неправильною, оскільки коментар з найвищим рейтингом чудово працює у проектах VS 2010 та VS 2017 c #, над якими я працюю. Повністю кваліфікований простір імен повинен використовуватися для вказівки класу при налаштуванні псевдоніма, але після налаштування псевдонім працює в межах визначеної області.
J-Americano

Мені довелося дуже детально прочитати відповідь Яна та його коментарі, перш ніж я зрозумів, чого він шукає. Він хоче оголосити псевдонім класу в одному місці , а не додавати його вгорі кожного файлу, що посилається на клас. Мені не відомі жодні сильно набрані мови, які б це підтримували. (Якщо хтось знає таку мову, я хотів би про це знати.) Я відредагував заголовок, щоб зробити це зрозумілішим.
ToolmakerSteve

До речі, для тих, хто намагається зробити щось подібне: якщо це класи, які ви визначаєте, то підхід C # полягає у визначенні interface, який реалізують усі ваші класи. Як згадувалось у відповіді chills42 . Потім ви можете визначити "службу" або "фабрику", яка повертає об'єкт, який реалізує цей інтерфейс, залежно від поточних обставин (наприклад, платформи / ОС) або конфігураційного файлу.
ToolmakerSteve

Відповіді:


129

Ви не можете . Наступне найкраще, що ви можете зробити, - це мати usingдекларації у файлах, що використовують клас.

Наприклад, ви можете переписати залежний код, використовуючи псевдонім імпорту (як квазізамінник typedef):

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

На жаль, це потрібно ввести в кожну область / файл, що використовує ім'я.

Тому я не знаю, чи це практично у вашому випадку.


9
Якби він міг знаходитись у верхній частині файлу, що містив початковий клас: це було б чудово. Але його usingпотрібно додати до всіх непрацюючих кодів. І це також заперечує значення наявності одного псевдоніма, що дозволяє мені переключити всіх користувачів існуючого ColorSchemeкласу на використання нового класу - без змін. Іншими словами: я хочу присвоїти ColorSchemeклас іншому класу.
Ян Бойд,

Чи є спосіб досягти того самого і поширити псевдонім із успадкуванням. тобто всі класи, що розширюють MyClass, зможуть використовувати ColorScheme замість the.Fully.Qualified ... ColorScheme, просто додавши оператор using у вихідний файл MyClass?
Флоріан

Ну, це було дуже практично для мого випадку. Нарешті C # перестане малювати мої шляхи до файлів.
ElDoRado1239

25

Ви можете створити псевдонім для свого класу, додавши цей рядок коду:

using Outlook2007ColorScheme = YourNameSpace.ColorScheme;

Назва "ColorScheme" не існує в поточному контексті
Ян Бойд

7
вам потрібна Fully.Qualified.Namespace.Of.ColorScheme
Jamie Pate

Я думав, що в C # таким чином можна використовувати лише простори імен (а не класи), де у VB.Net ви можете використовувати простори імен або класи псевдонімів Imports. Я помиляюся?
Нік

Вам не потрібно повністю кваліфіковане ім’я, якщо ви розміщуєте usingдирективу всередині простору імен, наприклад, коли вам потрібен псевдонім вашого власного класу.
Ельведін Хамзагіч

12

Вам потрібен ( Factory | Singleton ), залежно від ваших вимог. Передумова полягає в тому, щоб зробити так, щоб клієнтський код не знав, яку кольорову схему він отримує. Якщо колірна гамма повинна бути широкою, то однотонний повинен бути в порядку. Якщо ви можете використовувати іншу схему за різних обставин, фабричний шаблон, мабуть, шлях. У будь-якому випадку, коли кольорову схему потрібно змінити, код потрібно змінити лише в одному місці.

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; }
    }
}

Це виглядає як менша фабрика, а більше слабка спроба одностороннього зразка. Фабрика, швидше за все, буде параметризувати метод створення; у вас буде щось на зразок: загальнодоступна статична ColorScheme GetColorScheme (дескриптор рядка);
OwenP

Правда - основна ідея полягає в тому, щоб переконатися, що, коли вийде Office 2012, код повинен змінитись лише в 1 місці.
Кріс Марасті-Георг

1
Це, безумовно, працює, але, безперечно, це рішення корпоративної простої проблеми.
Ян Бойд

11

Ви не можете псевдонім імені класу в 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) { ... }
}

Ох, вибачте. Цей код не компілюється:

введіть тут опис зображення

Моє питання полягало в тому, як псевдонім класу в C #. Це неможливо зробити. Є речі, які я можу зробити, але не псевдонім назви класу в C #:

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

Але ці обхідні шляхи включають порушення існуючого коду: це не варіант.

Якщо люди залежать від присутності ColorSchemeкласу, я повинен фактично скопіювати / вставити ColorSchemeклас.

Іншими словами: я не можу псевдонім імені класу в C #.

Це контрастує з іншими об’єктно-орієнтованими мовами, де я міг би визначити псевдонім:

ColorScheme = Outlook2007ColorScheme

і я б закінчив.


21
Ви можете абсолютно псевдонім імені класу в C #. "використовуючи <псевдонім> = <цілком_кваліфіковане_ ім'я>;"
clemahieu

7
LIke @clemahieu сказав, що ви абсолютно можете псевдонімом назви класу, вам просто потрібно використовувати повністю кваліфіковане ім'я. Крім того, якщо ви встановлюєте псевдонім загального класу, вам може знадобитися додати класифікатор загального класу. Наприклад: використання ShortName = MyNamespace.SubNamespace.GenericClass <MyType>;
Dan Morphis,

11
Голос проти - ви заявили: "Ви не можете псевдонім назви класу в C #." Ти можеш. Що ви не можете зробити, це псевдонім класу так, як ви хочете - це цілком виправдана вимога, але ваше твердження неправильне.
Tom W

8
Як зазначали кілька плакатів, необхідність використання кваліфікованого імені жодним чином не забороняє псевдоніми. Ви можете псевдонім класу. Вам просто потрібно використовувати повну назву для цього. Вам може здатися це незручним, але це не робить твердження "Ви не можете псевдонім класу в C #" істинним. Можливо, спосіб використання псевдонімів у C # відрізняється від того, що ви очікували. Це добре - якщо це так, заявіть це. Але ви можете псевдонім назви класу в C #, оскільки в специфікації зазначено, що ви можете це зробити, відповідно до визначення, яке воно надає.
Tom W

5
Мені подобається, як ми, програмісти, будемо робити свої заяви між рядками. Що насправді говорить Ян, так це те, що C # німий і зламаний, тому що він не може зробити простих основних дій, які хтось хотів би зробити і мав би це зробити. Він правий - незалежно від того, чи конкретна семантика вас радує.
IQpierce


6

Я додаю цей коментар для користувачів, які знайшли це ще довго після того, як 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 #.


Це було б ще більш очевидним , якщо ви показали декларацію іншого класу: namespace Fully.Qualified.Namespace{ public class Example {... public void DoStuff(){... }... } }.
ToolmakerSteve

1
Щоб бути зрозумілим, це відрізняється від того, що шукає Ян. Ян має ситуацію, коли він не може (або не хоче) змінювати вихідні файли, що посилаються на клас. Він хоче спосіб змінити лише в одному місці у своєму додатку чи бібліотеці , в результаті чого, здається, є клас із потрібним ім'ям, яким можуть користуватися всі інші коди [без необхідності додавати цей оператор "using" до декількох джерел файли - наприклад, джерело може бути недоступним для зміни].
ToolmakerSteve

4

Згладжування того, як ви хотіли б це зробити, не буде працювати в 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;.

3

Припускаю, ви завжди можете успадкувати від базового класу, нічого не додавши

public class Child : MyReallyReallyLongNamedClass {}

ОНОВЛЕННЯ

Але якщо у вас є можливість рефакторингу 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, але в різних namespaces. Процитуючи PEP-20: Zen of Python :

Простори імен - одна чудова ідея - давайте зробимо ще більше!

Сподіваюся, це допомагає


2
завжди, якщо ви не можете: наприклад, запечатаний клас
mikus

але це не спрацьовує у багатьох випадках. наприклад, публічний клас MyList: List {} - якщо пізніше спробувати MyList xyz = something.ToList (); ти застрягнеш.
Offler

@Offler Ви могли б (і, мабуть, повинні) вдатися до newключового слова для таких методів або навіть придумати власні ExtensionMethods, так? У будь-якому випадку, я твердо переконаний, що ви завжди повинні використовувати класи колекції ванілі (тобто словник, список, IEnumerable, IQueryable тощо) із користувацькими моделями / ViewModels / POCO. Як заявляє Mvc: Конвенція про конфігурацію
percebus

@percebus працює не у всіх випадках. Я намагаюся перетворити старовинний код, коли частини використовують api, який більше не підтримується, на новий. Код durign трансформації буде змінений іншими, і він все ще повинен бути рунабельним - тому обидва вони повинні бути використані зараз. перетворення речей понад 700 000 LOC (без коментарів) і, незважаючи на це, буде зручним для використання, якби був можливий псевдонім стилю c ++ - і вам потрібно лише одне місце у файлі, щоб замінити клас псевдоніма реалізацією з будь-якого з них.
Offler

RE-POST для EDIT @Offler Для того, що ви описуєте звук, вам потрібно щось на зразок заводу з інтерфейсами. IColorScheme oColorScheme = ColorSchemeFactory.Create(); Також, можливо, ви захочете вивчити ін’єкцію залежності
percebus

2

Чи можна перейти на використання інтерфейсу?

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

Це добре працювало б із заводським зразком, як це показав Кріс Марасті-Георг


Це може бути, але я не збираюся більше витрачати на це час, а не перейменовувати клас, який є "поточною" кольоровою схемою для використання.
Ян Бойд

0

Це дуже пізня часткова відповідь - але якщо ви визначите той самий клас "ColorScheme", в тому ж просторі імен "Outlook", але в окремих збірках, одна з яких називається Outlook2003, а інша Outlook2007, то все, що вам потрібно зробити, це посилатися на відповідну збірку .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.