如何在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类,但是makeOutlook2003ColorSchemeOutlook2007ColorSchemeclass是非静态的。然后,静态ColorScheme类中的静态变量可以指向“ true”配色方案:

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

private class CustomColorScheme 
{ 
   ...
}

private class Outlook2008ColorScheme : CustomColorScheme 
{
    ...
}

private class Outlook2003ColorScheme : CustomColorScheme 
{
   ...
}

但这需要我将完全由只读静态Colors组成的类转换为可重写的属性,然后我的ColorScheme类需要将30个不同的属性获取器转换为所包含的对象。

只是打字太多了。

所以我的下一个想法是给该类起别名:

public static ColorScheme = Outlook2007ColorScheme;

但这不能编译。

如何将静态类别名为另一个名称?


更新:有人可以添加答案“您不能在C#中执行此操作”,所以我可以将其标记为可接受的答案。希望得到相同问题答案的其他任何人都可以找到该问题,接受的答案以及许多可能有用或可能没有有用的解决方法。

我只想结束这个问题。


即使您不想执行它,您也可能会接受克里斯的回答
devio

2
这不是答案,而是一种解决方法。答案是,您不能-至少要等到有人出现并发布实际的语法才能这样做时,才能这样做。
伊恩·博伊德

1
对于来这里的任何人,接受的答案都是错误的,因为评分最高的评论在我正在从事的VS 2010和VS 2017 c#项目中正常工作。设置别名时,必须使用完全限定的名称空间来指定类,但是一旦设置,别名就会在其定义的范围内起作用。
J-Americano于2008年

在我了解他的要求之前,我必须仔细阅读Ian的回答和他的评论。他想在一个地方声明一个类别,而不是必须将其添加到引用该类的每个文件的顶部。我不知道任何支持此功能的强类型语言。(如果有人知道这种语言,我想知道。)我已经编辑了标题,以使其更清楚。
ToolmakerSteve

顺便说一句,对于任何尝试做类似事情的人:如果您正在定义这些类,则C#方法是定义一个interface,由您所有类实现。如chills42的答案中所述。然后,您可以定义“服务”或“工厂”,根据当前情况(例如,平台/操作系统)或配置文件,该对象将返回实现该接口的对象。
ToolmakerSteve

Answers:


129

你不能。您可以做的第二件事是using在使用该类的文件中声明。

例如,您可以使用导入别名(作为准typedef替代品)重写从属代码:

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

不幸的是,这需要进入使用该名称的每个范围/文件。

因此,我不知道这是否适合您的情况。


9
如果可以放在包含原始类的文件的顶部,那就太好了。但using必须将其添加到所有损坏的代码中。而且它还否定了具有单个别名的值,这使我可以将现有ColorScheme类的所有用户切换为使用新类-无需更改。换句话说:我想将该ColorScheme类别名为另一个类。
伊恩·博伊德

有没有一种方法可以做到这一点,并通过继承传播别名。即所有扩展MyClass的类都可以通过仅在MyClass源文件中添加using语句来使用ColorScheme而不是the.Fully.Qualified ... ColorScheme?
Florian Burel

好吧,对于我的情况来说,这非常实用。最后,C#将停止绘制我的文件路径。
ElDoRado1239

25

您可以通过添加以下代码行来为您的班级添加别名:

using Outlook2007ColorScheme = YourNameSpace.ColorScheme;

名称“ ColorScheme”在当前上下文中不存在
Ian Boyd

7
您需要Fully.Qualified.Namespace.Of.ColorScheme
Jamie Pate

我认为在C#中只能以这种方式对名称空间(而不是类)进行别名,而在VB.Net中,您可以使用来对名称空间或类进行别名Imports。我错了吗?
尼克

如果将using指令放在名称空间中,则不需要完全限定的名称,例如,当您需要自己类的别名时。
Elvedin Hamzagic

12

您需要一个(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; }
    }
}

看起来好像不像是工厂,而更像是对单例模式的弱尝试。工厂将更有可能参数化创建方法;您将拥有更多类似的东西:公共静态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#中为类名别名:

  • 改变大家谁依赖于ColorSchemeusing ColorScheme代替(代码变化的解决方法,因为我无法别名)
  • 更改所有依赖ColorScheme使用工厂模式的人,使其成为多态类或接口(代码更改解决方法,因为我无法使用别名)

但是这些解决方法涉及破坏现有代码:不是一种选择。

如果人们依靠一ColorScheme堂课的存在,我实际上必须复制/粘贴一ColorScheme堂课。

换句话说:我不能在C#中为类名加上别名。

这与其他可以定义别名的面向对象语言形成对比:

ColorScheme = Outlook2007ColorScheme

我会做的。


21
您绝对可以在C#中为类名加上别名。“使用<别名> = <完全合格的名称>;”
clemahieu

7
就像@clemahieu所说,您绝对可以为类名起别名,您只需要使用完全限定名即可。此外,如果为通用类添加别名,则必须添加通用类限定符。例如:using ShortName = MyNamespace.SubNamespace.GenericClass <MyType>;
Dan Morphis

11
Downvote-您已声明“您不能在C#中为类名加上别名。” 您可以。您不能做的就是以想要的方式为类添加别名-这是很合理的要求,但是您的陈述是错误的。
汤姆W

8
正如一些发布者所指出的那样,必须使用限定名称绝不能阻止别名。您可以为该类命名。您只需要使用完全限定的名称即可。您可能会觉得这很不方便,但是它不会使“您不能在C#中为类名加上别名”这样的语句成为真实。在C#中,别名的工作方式可能与您期望的不同。很好-如果是这样,请声明。但是您可以在C#中为类名加上别名,因为规范指出您可以按照其提供的定义来这样做。
汤姆W

5
我喜欢我们的程序员如何在各行之间进行声明。伊恩(Ian)真正在说的是C#笨拙,因为它无法完成任何人都想做且应该能够做的简单的基本事情。他是正确的-特定的语义是否使您感到高兴。
IQpierce

10

试试这个:

using ColorScheme=[fully qualified].Outlook2007ColorScheme

名称“ ColorScheme”在当前上下文中不存在
Ian Boyd

2
您需要Fully.Qualified.Namespace.Of.ColorScheme
Jamie Pate

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
要明确的是,这与Ian寻求的是不同的。伊恩(Ian)有一种情况,他无法(或不想)更改引用某个类的源文件。他想要一种只在其应用程序或库中的一个位置进行更改的方法,从而导致看起来像是具有所需名称的类,而所有其他代码都可以使用[而不必将“ using”语句添加到多个源中文件-例如,该来源可能无法更改]。
制造商史蒂夫

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自身的能力:由于缺少namespaces,类名通常不必要地长。

如果你看到案件ApiLoginUserDataBaseUserWebPortalLoginUser,通常是缺乏的迹象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:Python的禅宗

命名空间是一个很棒的主意-让我们做更多这些吧!

希望这可以帮助


2
总是,除非您不能:例如密封课程
mikus,2016年

但这在很多情况下是行不通的。例如,公共类MyList:列表{}-如果以后再尝试MyList xyz = something.ToList(); 你会被卡住。
Offler

@Offler您可以(可能应该)new对此类方法使用任何一个关键字,甚至可以提出自己的ExtensionMethods,对吗?无论如何,我强烈建议您始终将Vanilla Collection类(即Dictionary,List,IEnumerable,IQueryable等)与自定义Model / ViewModels / POCO一起使用。正如Mvc所言:约定优于配置
percebus

@percebus并非在所有情况下都有效。我尝试将老式的Code whre零件转换为使用不再支持较新版本的api。严格的转换代码将由其他人更改,并且仍应可运行-因此两者都应立即可用。如果可以使用c ++样式别名,那么将超过700.000 LOC的东西聚合(不加注释),并且仍然让它可以运行会更容易-并且您只需要在文件中放置一个位置,即可用其中一个的实现替换别名类。
Offler

重新发布以进行编辑 @Offler对于您所描述的声音,您需要像带有接口的Factory之类的东西。 IColorScheme oColorScheme = ColorSchemeFactory.Create(); 另外,您可能想研究依赖注入
percebus

2

是否可以更改为使用界面?

也许您可以创建一个 IColorScheme所有类都实现接口?

这将与Chris Marasti-Georg所示的工厂模式很好地配合


可能是这样,但我不会再花时间在上面,而是重命名要使用的“当前”配色方案的类。
伊恩·博伊德

0

这是一个很晚的局部答案-但是,如果在相同的命名空间“ Outlook”中但在单独的程序集中定义了相同的类“ ColorScheme”,但在一个单独的程序集中,一个名为Outlook2003,另一个在Outlook2007中,那么您要做的就是引用适当的程序集。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.