Sınıfı kullanan her dosyaya bir kod satırı eklemeye gerek kalmadan C # 'da bir sınıf adını nasıl diğer adlar oluşturabilirim?


88

Bir sınıf adı için bir takma ad oluşturmak istiyorum. Aşağıdaki sözdizimi mükemmel olur:

public class LongClassNameOrOneThatContainsVersionsOrDomainSpecificName
{
   ...
}

public class MyName = LongClassNameOrOneThatContainsVersionOrDomainSpecificName;

ama derlenmeyecek.


Misal

Not Bu örnek yalnızca kolaylık sağlamak için verilmiştir. Tüm sistemin tasarımını değiştirmeyi önererek bu sorunu çözmeye çalışmayın. Bu örneğin varlığı veya yokluğu orijinal soruyu değiştirmez.

Bazı mevcut kodlar, statik bir sınıfın varlığına bağlıdır:

public static class ColorScheme
{
   ...
}

Bu renk düzeni, Outlook 2003 renk düzenidir. Outlook 2003 renk düzenini korurken bir Outlook 2007 renk düzeni tanıtmak istiyorum:

public static class Outlook2003ColorScheme
{
   ...
}

public static class Outlook2007ColorScheme
{
   ...
}

Ama hala kodun adı verilen statik bir sınıfın varlığına bağlı olduğu gerçeğiyle karşı karşıyayım ColorScheme. İlk düşüncem, ColorSchemeya Outlook2003da şunlardan miras alacağım bir sınıf oluşturmaktı Outlook2007:

public static class ColorScheme : Outlook2007ColorScheme
{
}

ancak statik bir sınıftan miras alamazsınız.

Bir sonraki düşüncem, statik ColorSchemesınıfı oluşturmak , ancak statik olmayan yapmak Outlook2003ColorSchemeve Outlook2007ColorSchemesınıflamaktı. Ardından, statik ColorSchemesınıftaki statik bir değişken, "doğru" renk şemalarından birine işaret edebilir:

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

private class CustomColorScheme 
{ 
   ...
}

private class Outlook2008ColorScheme : CustomColorScheme 
{
    ...
}

private class Outlook2003ColorScheme : CustomColorScheme 
{
   ...
}

ancak bu, tamamen okunabilir statik Renklerden oluşan bir sınıfı, geçersiz kılınabilen özelliklere dönüştürmemi gerektirecek ve daha sonra ColorSchemesınıfımın, içerilen nesneye inen 30 farklı özellik alıcıya sahip olması gerekecekti.

Bu çok fazla yazmak.

Bu yüzden bir sonraki düşüncem sınıfı takma ad vermek oldu:

public static ColorScheme = Outlook2007ColorScheme;

Ama bu derlemez.

Statik bir sınıfı başka bir ada nasıl takma ad verebilirim?


Güncelleme: Birisi lütfen "Bunu C # ile yapamazsınız" cevabını ekleyebilir mi , böylece bunu kabul edilen cevap olarak işaretleyebilirim. Aynı sorunun cevabını isteyen başka biri bu soruyu, kabul edilen cevabı ve yararlı olabilecek veya olmayabilecek bir dizi geçici çözümü bulacaktır.

Sadece bu soruyu kapatmak istiyorum.


uygulamak istemeseniz bile Chris'in cevabını kabul edebilirsiniz
devio

2
Cevap değil, geçici bir çözüm. Cevap şu ki, yapamazsınız - en azından birisi gelip bunu yapmak için gerçek sözdizimini gönderene kadar.
Ian Boyd

1
Buraya gelen herkes için, kabul edilen cevap yanlıştır çünkü en yüksek puan alan yorum üzerinde çalıştığım VS 2010 ve VS 2017 c # projelerinde gayet iyi çalışıyor. Takma adı ayarlarken sınıfı belirtmek için tam nitelikli ad alanı kullanılmalıdır, ancak takma ad bir kez ayarlandıktan sonra tanımlanan kapsam dahilinde çalışır.
J-Americano

Ne aradığını anlamadan önce Ian'ın cevabını ve yorumlarını çok detaylı okumak zorunda kaldım. Sınıfa başvuran her dosyanın en üstüne eklemek yerine , tek bir yerde bir sınıf diğer adı bildirmek istiyor . Bunu destekleyen kesin olarak yazılmış dillerden haberdar değilim . (Birisi böyle bir dili biliyorsa, bunu bilmek isterim.) Bunu daha anlaşılır hale getirmek için başlığı düzenledim.
ToolmakerSteve

BTW, benzer bir şey yapmaya çalışan herkes için: eğer bunlar sizin tanımladığınız sınıflarsa, o zaman C # yaklaşımı, interfacetüm sınıflarınızın uyguladığı bir anı tanımlamaktır . Chills42'nin cevabında belirtildiği gibi . Daha sonra, mevcut koşullara (örn. Platform / OS) veya bir yapılandırma dosyasına bağlı olarak, bu arayüzü uygulayan bir nesneyi döndüren bir "hizmet" veya "fabrika" tanımlayabilirsiniz.
ToolmakerSteve

Yanıtlar:


131

Yapamazsın . Bir sonraki en iyi şey olabilir yapmak zorunda olduğu usingsınıfını kullanın dosyalarda bildirimleri.

Örneğin, bağımlı kodu bir içe aktarma takma adı kullanarak (yarı typedefikame olarak) yeniden yazabilirsiniz :

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

Ne yazık ki bu, adı kullanan her kapsama / dosyaya girmelidir.

Bu nedenle, sizin durumunuzda bunun pratik olup olmadığını bilmiyorum.


9
Orijinal sınıfı içeren dosyanın en üstüne gidebilseydi: harika olurdu. Ancak usingtüm bozuk koda eklenmelidir. Ayrıca, mevcut ColorSchemesınıfın tüm kullanıcılarını değişiklik yapmadan yeni bir sınıf kullanımına geçirmeme izin veren tek bir takma ada sahip olma değerini de olumsuzlar . Başka bir deyişle: ColorSchemesınıfı başka bir sınıfa takma ad vermek istiyorum .
Ian Boyd

Aynısını elde etmenin ve takma adı miras yoluyla yaymanın bir yolu var mı? Yani MyClass'ı genişleten tüm sınıflar, sadece MyClass kaynak dosyasına using ifadesini ekleyerek.Fully.Qualified ... ColorScheme yerine ColorScheme kullanabilir mi?
Florian Burel

Benim durumum için çok pratikti. Sonunda C # dosya yollarımı çizmeyi bırakacak.
ElDoRado1239

25

Bu kod satırını ekleyerek sınıfınız için bir takma ad oluşturabilirsiniz:

using Outlook2007ColorScheme = YourNameSpace.ColorScheme;

'ColorScheme' adı mevcut bağlamda mevcut değil
Ian Boyd

7
Fully.Qualified.Namespace.Of.ColorScheme
Jamie Pate

C # 'da yalnızca ad alanlarını (sınıfları değil) bu şekilde değiştirebileceğini düşündüm, burada VB.Net'te ad alanlarını veya Imports. Yanlış mıyım?
Nick

usingYönergeyi kendi ad alanına koyarsanız , örneğin kendi sınıfınızın takma adına ihtiyaç duyduğunuzda, tam olarak nitelenmiş bir ada ihtiyacınız yoktur.
Elvedin Hamzagic

12

Gereksinimlerinize bağlı olarak bir ( Fabrika | Singleton ) istiyorsunuz . Buradaki amaç, müşteri kodunun hangi renk şemasını aldığını bilmek zorunda kalmaması için bunu yapmaktır. Renk şeması uygulama genişliğinde olacaksa, bir tek ton iyi olmalıdır. Farklı koşullarda farklı bir şema kullanacaksanız, büyük olasılıkla bir Fabrika düzeni gidebilirsiniz. Her iki durumda da, renk şemasının değişmesi gerektiğinde, kodun yalnızca tek bir yerde değiştirilmesi gerekir.

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

Bu daha az bir fabrika ve daha çok tekil bir model için zayıf bir girişim gibi görünüyor. Bir fabrikanın yaratma yöntemini parametreleştirmesi daha olasıdır; daha çok şuna benzer bir şeye sahip olursunuz: public static ColorScheme GetColorScheme (string descriptor);
OwenP

Doğru - temel fikir, 2012 ofisinin çıktığından emin olmaktır, kodun yalnızca 1 yerde değiştirilmesi gerekir.
Chris Marasti-Georg

1
Bu kesinlikle işe yarıyor, ancak kesinlikle basit bir soruna kurumsal bir çözüm.
Ian Boyd

11

C # 'da bir sınıf adına takma ad veremezsiniz.

C # 'da bir sınıf adına takma ad vermeyen yapabileceğiniz şeyler vardır.

Ancak orijinal soruyu cevaplamak için: C # 'da bir sınıf adına takma ad veremezsiniz.


Güncelleme: İnsanlar neden usingişe yaramadığı konusunda kafası karışık . Misal:

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

Ve her şey çalışıyor. Şimdi yeni bir sınıf ve takma ad oluşturmak istiyorum ColorScheme(böylece hiçbir kodun değiştirilmesine gerek kalmaz ):

ColorScheme.cs

using ColorScheme = Outlook2007ColorScheme;

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

Ohh, üzgünüm. Bu kod derlemez:

görüntü açıklamasını buraya girin

Sorum, C # 'da bir sınıfın nasıl takma adı verileceğiydi . Bu yapılamaz. C # 'da bir sınıf adına takma ad vermeyen yapabileceğim şeyler var :

  • bağlıdır değişim herkes ColorSchemeiçin using ColorSchemeyerine (kod değişikliği geçici çözüm i takma yapamam çünkü)
  • ColorSchemefabrika kalıbı kullanmaya bağlı olan herkesi değiştir, onlara bir polimorfik sınıf veya arayüz (takma ad veremediğim için kod değişikliği geçici çözümü)

Ancak bu geçici çözümler, mevcut kodu kırmayı içerir: bir seçenek değil.

İnsanlar bir ColorSchemesınıfın varlığına bağlıysa, aslında bir ColorSchemesınıfı kopyalayıp yapıştırmam gerekir .

Başka bir deyişle: C # 'da bir sınıf adına takma ad veremem.

Bu, diğer adı tanımlayabileceğim diğer nesne yönelimli dillerle tezat oluşturuyor:

ColorScheme = Outlook2007ColorScheme

ve bitirdim.


22
C # 'da bir sınıf adını kesinlikle takma ad verebilirsiniz. "<alias_name> = <fully_qualified_name> kullanarak;"
clemahieu

8
LIke @clemahieu dedi ki, kesinlikle bir sınıf ismini değiştirebilirsin, sadece tam nitelikli ismi kullanmalısın. Ayrıca, genel bir sınıfa takma ad veriyorsanız, genel sınıf niteleyicisini eklemeniz gerekebilir. Örneğin: kullanma ShortName = MyNamespace.SubNamespace.GenericClass <MyType>;
Dan Morphis

11
Olumsuz oy - "C # 'da bir sınıf adına takma ad veremezsiniz" dediniz. Yapabilirsin. Ne yapamaz takma şekilde bir sınıftır sen istiyorum - oldukça haklı gerekliliktir ancak iş ifade doğru değil.
Tom W

8
Birkaç posterin de işaret ettiği gibi, nitelikli adı kullanmak hiçbir şekilde takma ad kullanımını engellemez. Sen edebilirsiniz sınıfını diğer ad. Bunu yapmak için tam nitelikli adı kullanmanız yeterlidir. Bunu uygunsuz bulabilirsiniz, ancak bu, 'C #' da bir sınıf adına takma ad veremezsiniz 'ifadesini doğru yapmaz. Belki de C # 'da takma ad işleminin çalışma şekli beklediğinizden farklıdır. Sorun değil - eğer durum buysa, bunu belirtin. Ancak C # 'da bir sınıf adına takma ad verebilirsiniz çünkü belirtim, sağladığı tanıma göre bunu yapabileceğinizi belirtir.
Tom W

5
Biz programcıların satırlar arasında ifadelerimizi nasıl vereceğini seviyorum. Ian'ın gerçekten söylediği şey, C # 'ın aptal ve bozuk olduğu çünkü herkesin yapmak isteyeceği ve yapabilmesi gereken basit bir şeyi yapamaz. O haklı - belirli anlambilim sizi mutlu edip etmediği.
IQpierce

10

bunu dene:

using ColorScheme=[fully qualified].Outlook2007ColorScheme

'ColorScheme' adı mevcut bağlamda mevcut değil
Ian Boyd

2
Fully.Qualified.Namespace.Of.ColorScheme
Jamie Pate

6

Bu yorumu OP'nin "cevabını" kabul etmesinden çok sonra bulan kullanıcılar için ekliyorum. C # 'da takma ad, sınıf adını tamamen nitelenmiş ad alanını kullanarak belirleyerek çalışır. Tanımlanmış bir takma ad, kapsamı içinde kullanılabilir. Misal.

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
  }

}

Hızlıca yazılan kod için özür dileriz, ancak umarım bu, kullanıcıların C # ile yapılamayacağına inanmaları için yanıltmasınlar diye bunun nasıl uygulanması gerektiğini açıklar.


Eğer gösterdi, bu daha net olurdu deklarasyon diğer sınıfın: namespace Fully.Qualified.Namespace{ public class Example {... public void DoStuff(){... }... } }.
ToolmakerSteve

1
Açık olmak gerekirse, bu Ian'ın aradığından farklı. Ian'ın bir sınıfa başvuran kaynak dosyalarını değiştiremeyeceği (veya değiştirmek istemediği) bir durumu var. Uygulamasında veya kitaplığında yalnızca bir yerde değişiklik yapmanın bir yolunu istiyor , bu da istenen ada sahip bir sınıf gibi görünen, diğer tüm kodların [bu "using" ifadesini birden çok kaynağa eklemek zorunda kalmadan kullanabilmesini sağlıyor dosyalar - örneğin bu kaynak değiştirilemeyebilir].
ToolmakerSteve

4

Bunu yapmak istediğiniz şekilde takma ad C # ile çalışmayacaktır. Bunun nedeni, takma adın söz usingkonusu dosya / ad alanıyla sınırlı olan yönerge aracılığıyla yapılmasıdır . Eski sınıf adını kullanan 50 dosyanız varsa, bu güncellenecek 50 yer anlamına gelir.

Bununla birlikte, kodunuzu olabildiğince az değiştirmenin kolay bir çözümü olduğunu düşünüyorum. Uygulama ile ColorSchemesınıfı gerçek sınıflara yaptığınız çağrılar için bir cephe haline getirin ve usinghangisini ColorSchemekullanacağınızı belirlemek için o dosyadaki öğesini kullanın.

Başka bir deyişle, şunu yapın:

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

Sonra arkasındaki kodunuzda hiçbir şeyi değiştirmeyin:

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

Daha sonra ColorSchemebir kod satırını ( using CurrentColorScheme = Outlook2008ColorScheme;) güncelleyerek değerlerini güncelleyebilirsiniz .

Burada birkaç endişe var:

  • Her yeni yöntem veya özellik tanımının daha sonra iki yerde, ColorSchemesınıfa ve sınıfa eklenmesi gerekecektir Outlook2007ColorScheme. Bu fazladan bir iştir, ancak bu gerçek eski kodsa, sık rastlanan bir durum olmamalıdır. Bonus olarak, kodColorScheme o kadar basittir ki, olası herhangi bir hata çok açıktır.
  • Statik sınıfların bu şekilde kullanılması bana doğal görünmüyor; Muhtemelen bunu farklı yapmak için eski kodu yeniden düzenlemeye çalışırdım, ancak durumunuzun buna izin vermeyebileceğini de anlıyorum.
  • Zaten ColorSchemedeğiştirdiğiniz bir sınıfınız varsa, bu yaklaşım ve diğerleri bir sorun olabilir. Bu sınıfa benzer şekilde yeniden adlandırmanızı ColorSchemeOldve ardından ona erişmenizi tavsiye ederim using CurrentColorScheme = ColorSchemeOld;.

3

Hiçbir şey eklenmeden her zaman temel sınıftan miras alabileceğinizi düşünüyorum.

public class Child : MyReallyReallyLongNamedClass {}

GÜNCELLEME

Ancak classkendini yeniden düzenleme yeteneğiniz varsa : Bir sınıf adı, namespaces eksikliğinden dolayı genellikle gereksiz yere uzundur .

Siz vakaları görürseniz ApiLoginUser, DataBaseUser, WebPortalLoginUser, eksikliği göstergesidir genellikle namespacenedeniyle korku bu ismi Userkudreti çatışma.

Ancak bu durumda, yukarıdaki yazılarda belirtildiği gibinamespace takma ad kullanabilirsiniz.

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İsimlerin hepsinin nasıl olduğuna dikkat edin User, ancak farklı adlarda namespace. Alıntı PEP-20: Zen of Python :

İsim alanları, harika bir fikir - hadi onlardan daha fazlasını yapalım!

Bu yardımcı olur umarım


2
her zaman, yapamadığınız sürece: ör. mühürlü sınıf
mikus

ancak bu çoğu durumda işe yaramayacaktır. ör. genel sınıf MyList: List {} - daha sonra MyList xyz = something.ToList () denerseniz; sıkışıp kalacaksın.
Offler

@Offler Bu newtür yöntemler için her iki anahtar kelimeye de başvurabilirsin (ve muhtemelen yapmalısın) ya da kendi ExtensionMethods'unu bulabilirsin, değil mi? Her halükarda, özel Modeller / ViewModels / POCO'larla her zaman vanilya Koleksiyonu sınıflarını (örneğin Sözlük, Liste, IEnumerable, IQueryable, vb.) Kullanmanız gerektiğine inanıyorum.
Mvc'nin

@percebus her durumda çalışmaz. Parçaların artık desteklenmeyen bir api kullandığı eski Code'u daha yenisine dönüştürmeye çalışıyorum. durign dönüşüm kodu başkaları tarafından değiştirilecek ve yine de çalıştırılabilir olmalıdır - bu nedenle ikisi de şu anda kullanılabilir olmalıdır. 700.000 LOC'nin üzerindeki şeyleri (yorumsuz) dönüştürmek ve yine de çalıştırılabilir olmasına izin vermek daha kolay olurdu, eğer bir c ++ tarzı takma ad mümkünse - ve bir takma ad sınıfını her ikisinden de uygulama ile değiştirmek için bir dosyada yalnızca bir yere ihtiyacınız var.
Offler

@Offler EDIT için YENİDEN POSTA Arabirimli bir Fabrika gibi ihtiyacınız olan sesi tanımladığınız için. IColorScheme oColorScheme = ColorSchemeFactory.Create(); Ayrıca, Bağımlılık Enjeksiyonuna da
percebus

2

Arayüz kullanmaya geçmek mümkün mü?

Belki IColorSchemetüm sınıfların uyguladığı bir arayüz oluşturabilirsiniz ?

Bu, Chris Marasti-Georg tarafından gösterildiği gibi fabrika modeliyle iyi çalışacaktır.


Olabilir, ancak artık kullanılacak "mevcut" renk şeması olan sınıfı yeniden adlandırmak yerine üzerinde zaman harcamayacağım.
Ian Boyd

0

Bu çok geç bir kısmi cevap - ancak aynı 'ColorScheme' sınıfını aynı ad alanında 'Outlook' olarak tanımlarsanız, ancak biri Outlook2003 ve diğeri Outlook2007 olarak adlandırılan ayrı derlemelerde yapmanız gereken tek şey uygun derlemeye başvurmaktır. .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.