web-dev-qa-db-ja.com

クラスを使用するすべてのファイルにコード行を追加せずに、C#でクラス名をエイリアスするにはどうすればよいですか?

クラス名のエイリアスを作成したい。次の構文が最適です。

public class LongClassNameOrOneThatContainsVersionsOrDomainSpecificName
{
   ...
}

public class MyName = LongClassNameOrOneThatContainsVersionOrDomainSpecificName;

しかし、コンパイルはしません。


この例は、便宜のためにのみ提供されています。システム全体の設計を変更することを提案して、この特定の問題を解決しようとしないでください。この例の存在または欠如は、元の質問を変更しません。

既存のコードの一部は、静的クラスの存在に依存しています。

public static class ColorScheme
{
   ...
}

この配色は、Outlook 2003の配色です。 Outlook 2003の配色を保持しながら、Outlook 2007の配色を導入したい:

public static class Outlook2003ColorScheme
{
   ...
}

public static class Outlook2007ColorScheme
{
   ...
}

しかし、コードはColorSchemeと呼ばれる静的クラスの存在に依存するという事実にまだ直面しています。私が最初に考えたのは、Outlook2003またはOutlook2007から派生するColorSchemeクラスを作成することでした。

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 
{
   ...
}

しかし、そのためには読み取り専用の静的なColor全体で構成されるクラスをオーバーライド可能なプロパティに変換する必要があり、ColorSchemeクラスには30の異なるプロパティゲッターが含まれるオブジェクトにまとめられる必要があります。

入力が多すぎます。

だから私の次の考えはクラスをエイリアスすることでした:

public static ColorScheme = Outlook2007ColorScheme;

しかし、それはコンパイルされません。

静的クラスを別の名前にエイリアスするにはどうすればよいですか?


更新:誰かが答えを追加してもらえますか "C#でこれを行うことはできません"。回答。同じ質問に対する回答を必要とする他の人は、この質問、受け入れられた回答、および役立つ可能性のある、または役に立たない多くの回避策を見つけるでしょう。

この質問を締めくくりたいだけです。

69
Ian Boyd

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) { ... }
}

そして、すべてが機能します。今、私はnewクラスを作成し、aliasColorSchemeを作成します(そのためコードを変更する必要はありません) :

ColorScheme.cs

using ColorScheme = Outlook2007ColorScheme;

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

ああ、すみません。このコードはコンパイルされません:

enter image description here

私の質問は、C#のクラスをaliasにする方法でした。できません。 not C#でクラス名のエイリアスを作成することができます:

  • 代わりにColorSchemeに依存するすべての人をusingColorSchemeに変更します(エイリアスを変更できないため、コード変更の回避策)
  • ColorSchemeに依存するすべての人をファクトリパターンを使用してポリモーフィッククラスまたはインターフェイスに変更します(エイリアスできないため、コード変更の回避策)

ただし、これらの回避策には、既存のコードを壊すことが含まれます。オプションではありません。

人々がColorSchemeクラスの存在に依存している場合、実際にColorSchemeクラスをコピー/貼り付けする必要があります。

つまり、C#でクラス名をエイリアス化することはできません。

これは、エイリアスを定義できる他のオブジェクト指向言語とは対照的です。

ColorScheme = Outlook2007ColorScheme

完了します。

11
Ian Boyd

元のクラス名を変更する場合、インポートエイリアスをtypedefの代替として使用して依存コードを書き換えることができます。

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

これは、通常のusingsと同様に、ファイル/ネームスペースの先頭に配置する必要があります。

しかし、これがあなたの場合に実用的かどうかはわかりません。

110
Konrad Rudolph

次のコード行を追加して、クラスのエイリアスを作成できます。

using Outlook2007ColorScheme = YourNameSpace.ColorScheme;
21
mohammedn

必要に応じて、( Factory | Singleton )が必要です。前提は、クライアントコードが取得しているカラースキームを知る必要がないようにすることです。カラースキームをアプリケーション全体に適用する必要がある場合は、シングルトンで十分です。異なる状況で異なるスキームを使用する場合は、おそらくFactoryパターンが最適です。いずれにせよ、配色を変更する必要がある場合、コードを1か所で変更するだけで済みます。

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

これを試して:

using ColorScheme=[fully qualified].Outlook2007ColorScheme
10
dpurrington

やりたい方法にエイリアスを付けることは、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);
}

その後、1行のコード(using CurrentColorScheme = Outlook2008ColorScheme;)を更新することにより、ColorSchemeの値を更新できます。

ここでいくつかの懸念事項:

  • 新しいメソッドまたはプロパティの定義はすべて、ColorSchemeクラスとOutlook2007ColorSchemeクラスの2つの場所に追加する必要があります。これは余分な作業ですが、これが真のレガシーコードである場合、頻繁に発生することはありません。ボーナスとして、ColorSchemeのコードは非常に単純なので、考えられるバグは非常に明白です。
  • この静的クラスの使用は、私には自然ではないようです。おそらくレガシーコードをリファクタリングして、これを別の方法で実行しようとするでしょうが、あなたの状況ではそれが許されないことも理解しています。
  • 置き換えようとしているColorSchemeクラスが既にある場合、この方法やその他の方法が問題になる可能性があります。そのクラスの名前をColorSchemeOldのような名前に変更し、using CurrentColorScheme = ColorSchemeOld;を介してアクセスすることをお勧めします。
4
Timothy

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
  }

}

すぐに入力されたコードをおologiesびしますが、C#で実行できないとユーザーが誤解しないように、これがどのように実装されるべきかを説明することが望まれます。

4
J-Americano

基本クラスから何も追加せずにいつでも継承できると思います

public class Child : MyReallyReallyLongNamedClass {}

[〜#〜] update [〜#〜]

ただし、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ですが、namespacesが異なることに注意してください。引用 PEP-20:Pythonの禅

名前空間は素晴らしいアイデアの1つです-それらをもっとやってみましょう!

お役に立てれば

3
percebus

インターフェイスの使用に変更することは可能ですか?

おそらく、すべてのクラスが実装するIColorSchemeインターフェイスを作成できますか?

これは、Chris Marasti-Georgが示す工場パターンでうまく機能します。

2
chills42

それは非常に遅い部分的な答えです-しかし、同じ名前空間 'Outlook'で同じクラス 'ColorScheme'を定義し、別のアセンブリ(Outlook2003および他のOutlook2007と呼ばれる)で定義する場合、必要なのは適切なアセンブリを参照することです。

0
Mark Farmiloe