Làm cách nào để đặt bí danh tên lớp trong C # mà không phải thêm dòng mã vào mọi tệp sử dụng lớp?


87

Tôi muốn tạo bí danh cho tên lớp. Cú pháp sau sẽ hoàn hảo:

public class LongClassNameOrOneThatContainsVersionsOrDomainSpecificName
{
   ...
}

public class MyName = LongClassNameOrOneThatContainsVersionOrDomainSpecificName;

nhưng nó sẽ không biên dịch.


Thí dụ

Lưu ý Ví dụ này chỉ được cung cấp để thuận tiện. Đừng cố gắng giải quyết vấn đề cụ thể này bằng cách đề xuất thay đổi thiết kế của toàn bộ hệ thống. Sự hiện diện hoặc thiếu của ví dụ này không thay đổi câu hỏi ban đầu.

Một số mã hiện có phụ thuộc vào sự hiện diện của một lớp tĩnh:

public static class ColorScheme
{
   ...
}

Phối màu này là phối màu Outlook 2003. tôi muốn giới thiệu một sơ đồ màu Outlook 2007, trong khi vẫn giữ lại sơ đồ màu Outlook 2003:

public static class Outlook2003ColorScheme
{
   ...
}

public static class Outlook2007ColorScheme
{
   ...
}

Nhưng tôi vẫn phải đối mặt với thực tế là mã phụ thuộc vào sự hiện diện của một lớp tĩnh được gọi ColorScheme. Suy nghĩ đầu tiên của tôi là tạo một ColorSchemelớp mà tôi sẽ kế thừa từ một trong hai Outlook2003hoặc Outlook2007:

public static class ColorScheme : Outlook2007ColorScheme
{
}

nhưng bạn không thể kế thừa từ một lớp tĩnh.

Suy nghĩ tiếp theo của tôi là tạo ColorSchemelớp tĩnh , nhưng tạo Outlook2003ColorSchemeOutlook2007ColorSchemecác lớp không tĩnh. Sau đó, một biến tĩnh trong ColorSchemelớp tĩnh có thể trỏ đến phối màu "true":

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

private class CustomColorScheme 
{ 
   ...
}

private class Outlook2008ColorScheme : CustomColorScheme 
{
    ...
}

private class Outlook2003ColorScheme : CustomColorScheme 
{
   ...
}

nhưng điều đó sẽ yêu cầu tôi chuyển đổi một lớp bao gồm các Màu tĩnh chỉ đọc thành các thuộc tính có thể ghi đè, và sau đó ColorSchemelớp của tôi sẽ cần có 30 bộ nhận thuộc tính khác nhau đưa vào đối tượng được chứa.

Đó chỉ là quá nhiều đánh máy.

Vì vậy, suy nghĩ tiếp theo của tôi là đặt bí danh cho lớp:

public static ColorScheme = Outlook2007ColorScheme;

Nhưng điều đó không biên dịch.

Làm cách nào để đặt bí danh một lớp tĩnh thành một tên khác?


Cập nhật: Ai đó có thể vui lòng thêm câu trả lời "Bạn không thể làm điều này trong C #" , vì vậy tôi có thể đánh dấu đó là câu trả lời được chấp nhận. Bất kỳ ai khác muốn câu trả lời cho cùng một câu hỏi sẽ tìm thấy câu hỏi này, câu trả lời được chấp nhận và một số cách giải quyết có thể hữu ích hoặc có thể không.

Tôi chỉ muốn kết thúc câu hỏi này.


bạn cũng có thể chấp nhận câu trả lời của Chris, ngay cả khi bạn không muốn thực hiện nó
lệch

2
Đó không phải là câu trả lời, đó là một cách giải quyết. Câu trả lời là bạn không thể - ít nhất là cho đến khi ai đó đến xung quanh và đăng cú pháp thực tế để làm điều đó.
Ian Boyd

1
Đối với bất kỳ ai đến đây, câu trả lời được chấp nhận là không chính xác vì nhận xét được đánh giá cao nhất hoạt động tốt trong các dự án c # VS 2010 và VS 2017 mà tôi đang thực hiện. Không gian tên đủ điều kiện phải được sử dụng để chỉ định lớp khi thiết lập bí danh, nhưng khi thiết lập bí danh sẽ hoạt động trong phạm vi được xác định của nó.
J-Americano

Tôi phải đọc rất chi tiết câu trả lời của Ian và những bình luận của anh ấy trước khi tôi hiểu anh ấy đang tìm kiếm điều gì. Anh ta muốn khai báo bí danh lớp ở một nơi , thay vì phải thêm bí danh đó vào đầu mỗi tệp tham chiếu đến lớp. Tôi không biết bất kỳ ngôn ngữ được đánh máy mạnh nào hỗ trợ điều này. (Nếu ai đó biết một ngôn ngữ như vậy, tôi muốn biết về nó.) Tôi đã chỉnh sửa tiêu đề để làm rõ hơn điều này.
ToolmakerSteve

BTW, dành cho bất kỳ ai đang cố gắng làm điều gì đó tương tự: nếu đây là các lớp bạn đang định nghĩa, thì phương pháp C # là xác định một interface, mà tất cả các lớp của bạn thực hiện. Như đã đề cập trong câu trả lời của chills42 . Sau đó, bạn có thể xác định "dịch vụ" hoặc "nhà máy" trả về một đối tượng triển khai giao diện đó, tùy thuộc vào trường hợp hiện tại (ví dụ: nền tảng / Hệ điều hành) hoặc trên tệp cấu hình.
ToolmakerSteve

Câu trả lời:


129

Bạn không thể . Điều tốt nhất tiếp theo bạn có thể làm là có các usingkhai báo trong các tệp sử dụng lớp.

Ví dụ: bạn có thể viết lại mã phụ thuộc bằng cách sử dụng bí danh nhập (như một typedefchất thay thế gần như):

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

Thật không may, điều này cần phải đi vào mọi phạm vi / tệp sử dụng tên.

Do đó, tôi không biết liệu điều này có thực tế trong trường hợp của bạn hay không.


9
Nếu nó có thể ở đầu tệp chứa lớp gốc: thì thật tuyệt. Nhưng usingphải được thêm vào tất cả các mã bị hỏng. Và nó cũng phủ nhận giá trị có một bí danh duy nhất, cho phép tôi chuyển tất cả người dùng của ColorSchemelớp hiện có sang sử dụng một lớp mới - mà không có thay đổi. Nói cách khác: tôi muốn đặt bí danh ColorSchemelớp này cho lớp khác.
Ian Boyd

Có cách nào để đạt được điều tương tự và truyền bí danh với tính kế thừa. tức là tất cả các lớp mở rộng MyClass sẽ có thể sử dụng ColorScheme thay vì ColorScheme.Fully.Qualified ... bằng cách chỉ thêm câu lệnh using trong tệp nguồn MyClass?
Florian Burel

Chà, nó rất thực tế cho trường hợp của tôi. Cuối cùng C # sẽ ngừng vẽ đường dẫn tệp của tôi.
ElDoRado1239

25

Bạn có thể tạo bí danh cho lớp của mình bằng cách thêm dòng mã sau:

using Outlook2007ColorScheme = YourNameSpace.ColorScheme;

Tên 'colorscheme' không tồn tại trong bối cảnh hiện nay
Ian Boyd

7
bạn cần Complete.Qualified.Namespace.Of.ColorScheme
Jamie Pate

Tôi đã nghĩ trong C # chỉ có thể đặt bí danh không gian tên (không phải lớp) theo cách này, trong đó trong VB.Net bạn có thể đặt bí danh không gian tên hoặc lớp bằng cách sử dụng Imports. Tôi có lầm không?
Nick

Bạn không cần tên đủ điều kiện nếu bạn đặt usingchỉ thị bên trong không gian tên của nó, ví dụ khi bạn cần một bí danh của lớp riêng của bạn.
Elvedin Hamzagic

12

Bạn muốn một ( Factory | Singleton ), tùy thuộc vào yêu cầu của bạn. Tiền đề là tạo ra nó để mã khách hàng không cần phải biết nó đang nhận được bảng màu nào. Nếu bảng màu nên được ứng dụng rộng rãi, thì nên sử dụng một lớp đơn. Nếu bạn có thể sử dụng một lược đồ khác trong các trường hợp khác nhau, thì một mẫu Factory có thể là cách tốt nhất. Dù bằng cách nào, khi bảng màu cần thay đổi, mã chỉ phải được thay đổi ở một nơi.

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

Điều này trông giống như một nhà máy ít hơn và nhiều nỗ lực yếu hơn đối với một mô hình singleton. Một nhà máy sẽ có nhiều khả năng tham số hóa phương pháp tạo; bạn sẽ có một cái gì đó giống như: public static ColorScheme GetColorScheme (string descriptor);
OwenP 28/10/08

Đúng - ý tưởng cơ bản là đảm bảo rằng khi office 2012 ra mắt, mã chỉ phải thay đổi ở một chỗ.
Chris Marasti-Georg

1
Điều này chắc chắn hoạt động, nhưng nó chắc chắn là một giải pháp phù hợp với doanh nghiệp cho một vấn đề đơn giản.
Ian Boyd

11

Bạn không thể đặt bí danh tên lớp trong C #.

Có những điều bạn có thể làm mà không phải là bí danh tên lớp trong C #.

Nhưng để trả lời câu hỏi ban đầu: bạn không thể đặt bí danh tên lớp trong C #.


Cập nhật: Mọi người đang bối rối tại sao usingkhông hoạt động. Thí dụ:

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

Và mọi thứ đều hoạt động. Bây giờ tôi muốn tạo một lớp mớibí danh ColorScheme cho nó (để không cần sửa đổi mã ):

ColorScheme.cs

using ColorScheme = Outlook2007ColorScheme;

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

Ohh tôi xin lỗi. Mã này không biên dịch:

nhập mô tả hình ảnh ở đây

Câu hỏi của tôi là làm thế nào để đặt bí danh một lớp trong C #. Nó không thể được thực hiện. Có những điều tôi có thể làm mà không phải là bí danh tên lớp trong C #:

  • thay đổi tất cả những người phụ thuộc vào ColorSchemeđể using ColorSchemethay thế (giải pháp thay đổi mã vì tôi không thể bí danh)
  • thay đổi tất cả những người phụ thuộc vào ColorSchemeđể sử dụng một mô hình gốc cho họ một lớp hoặc giao diện đa hình (giải pháp thay đổi mã vì tôi không thể bí danh)

Nhưng những cách giải quyết này liên quan đến việc phá vỡ mã hiện có: không phải là một tùy chọn.

Nếu mọi người phụ thuộc vào sự hiện diện của một ColorSchemelớp, tôi phải thực sự sao chép / dánColorScheme lớp.

Nói cách khác: tôi không thể đặt bí danh tên lớp trong C #.

Điều này trái ngược với các ngôn ngữ hướng đối tượng khác, nơi tôi có thể xác định bí danh:

ColorScheme = Outlook2007ColorScheme

và tôi sẽ hoàn thành.


21
Bạn hoàn toàn có thể đặt bí danh tên lớp trong C #. "using <alias_name> = <ful_qu Đủ_name>;"
clemahieu,

7
LIke @clemahieu cho biết, bạn hoàn toàn có thể đặt bí danh cho một tên lớp, bạn chỉ cần sử dụng tên đủ điều kiện. Ngoài ra, nếu bí danh của bạn là một lớp chung, bạn có thể phải thêm bộ định danh lớp chung. Ví dụ: using ShortName = MyNamespace.SubNamespace.GenericClass <MyType>;
Dan Morphis

11
Phản đối - bạn đã tuyên bố "Bạn không thể đặt bí danh tên lớp trong C #." Bạn có thể. Điều bạn không thể làm là đặt bí danh cho một lớp theo cách bạn muốn - đó là một yêu cầu khá hợp lý, nhưng tuyên bố của bạn không chính xác.
Tom W

8
Như một số áp phích đã chỉ ra, việc sử dụng tên đủ điều kiện không có cách nào cấm được răng cưa. Bạn có thể đặt bí danh cho lớp. Bạn chỉ cần sử dụng tên đủ điều kiện để làm như vậy. Bạn có thể thấy điều này bất tiện, nhưng nó không làm cho tuyên bố 'Bạn không thể bí danh tên lớp trong C #' đúng. Có lẽ cách hoạt động của răng cưa trong C # khác với những gì bạn mong đợi. Tốt thôi - nếu đúng như vậy, hãy nói rõ điều đó. Nhưng bạn có thể đặt bí danh tên lớp trong C # vì đặc tả nói rằng bạn có thể làm như vậy, theo định nghĩa mà nó cung cấp.
Tom W,

5
Tôi thích cách mà các lập trình viên của chúng tôi sẽ đưa ra các câu lệnh giữa các dòng. Những gì Ian thực sự đang nói là C # thật ngu ngốc và bị hỏng bởi vì nó không thể làm một điều cơ bản đơn giản mà bất kỳ ai cũng muốn làm và nên có thể làm. Anh ấy nói đúng - ngữ nghĩa cụ thể có khiến bạn hài lòng hay không.
IQpierce

10

thử đi:

using ColorScheme=[fully qualified].Outlook2007ColorScheme

Tên 'colorscheme' không tồn tại trong bối cảnh hiện nay
Ian Boyd

2
bạn cần Full.Qualified.Namespace.Of.ColorScheme
Jamie Pate

6

Tôi thêm nhận xét này cho những người dùng tìm thấy điều này rất lâu sau khi OP chấp nhận "câu trả lời" của họ. Bí danh trong C # hoạt động bằng cách chỉ định tên lớp bằng cách sử dụng không gian tên đủ điều kiện của nó. Một trong những định nghĩa, tên bí danh có thể được sử dụng trong phạm vi của nó. Thí dụ.

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
  }

}

Xin lỗi vì mã được nhập nhanh chóng nhưng hy vọng nó giải thích cách thực hiện điều này để người dùng không bị hiểu nhầm rằng nó không thể được thực hiện trong C #.


Đây sẽ là thậm chí rõ ràng hơn nếu bạn cho thấy tuyên bố của lớp khác: namespace Fully.Qualified.Namespace{ public class Example {... public void DoStuff(){... }... } }.
ToolmakerSteve

1
Nói rõ hơn, điều này khác với những gì Ian đang tìm kiếm. Ian có một tình huống mà anh ấy không thể (hoặc không muốn) thay đổi các tệp nguồn tham chiếu đến một lớp. Anh ấy muốn một cách để thực hiện thay đổi chỉ ở một vị trí trong ứng dụng hoặc thư viện của mình , dẫn đến những gì có vẻ là một lớp với tên mong muốn, mà tất cả các mã khác có thể sử dụng [mà không cần phải thêm câu lệnh "using" đó vào nhiều nguồn tệp - ví dụ: nguồn đó có thể không có sẵn để thay đổi].
ToolmakerSteve

4

Đặt biệt hiệu theo cách bạn muốn sẽ không hoạt động trong C #. Điều này là do việc tạo bí danh được thực hiện thông qua usingchỉ thị, được giới hạn trong tệp / không gian tên được đề cập. Nếu bạn có 50 tệp sử dụng tên lớp cũ, điều đó có nghĩa là 50 vị trí cần cập nhật.

Điều đó nói rằng, tôi nghĩ rằng có một giải pháp dễ dàng để làm cho mã của bạn thay đổi ở mức tối thiểu nhất có thể. Làm cho ColorSchemelớp này trở thành mặt tiền cho các cuộc gọi của bạn đến các lớp thực tế với việc triển khai và sử dụng usingtrong tệp đó để xác định ColorSchemebạn sử dụng.

Nói cách khác, hãy làm điều này:

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

Sau đó, trong mã của bạn phía sau, không thay đổi gì:

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

Sau đó, bạn có thể cập nhật các giá trị của ColorSchemebằng cách cập nhật một dòng mã ( using CurrentColorScheme = Outlook2008ColorScheme;).

Một vài mối quan tâm ở đây:

  • Sau đó, mọi phương thức hoặc định nghĩa thuộc tính mới sẽ cần phải được thêm vào hai nơi, vào ColorSchemelớp và vào Outlook2007ColorSchemelớp. Đây là công việc bổ sung, nhưng nếu đây là mã kế thừa thực sự, nó không phải là một sự xuất hiện thường xuyên. Như một phần thưởng, mã trongColorScheme quá đơn giản nên mọi lỗi có thể xảy ra đều rất rõ ràng.
  • Việc sử dụng các lớp tĩnh này có vẻ không tự nhiên đối với tôi; Tôi có thể sẽ cố gắng cấu trúc lại mã kế thừa để làm điều này theo cách khác, nhưng tôi cũng hiểu rằng tình huống của bạn có thể không cho phép điều đó.
  • Nếu bạn đã có một ColorSchemelớp mà bạn đang thay thế, thì cách tiếp cận này và bất kỳ cách nào khác có thể là một vấn đề. Tôi khuyên bạn nên đổi tên lớp đó thành một cái gì đó giống như ColorSchemeOld, và sau đó truy cập nó thông qua using CurrentColorScheme = ColorSchemeOld;.

3

Tôi cho rằng bạn luôn có thể kế thừa từ lớp cơ sở mà không cần thêm gì

public class Child : MyReallyReallyLongNamedClass {}

CẬP NHẬT

Nhưng nếu bạn có khả năng tự cấu trúc lại class: Tên lớp thường dài không cần thiết do thiếu namespaces.

Nếu bạn thấy trường hợp như ApiLoginUser, DataBaseUser, WebPortalLoginUser, thường là dấu hiệu của thiếu namespacedo sợ rằng tên Usermâu thuẫn sức.

Tuy nhiên, trong trường hợp này, bạn có thể sử dụng namespacebí danh , vì nó đã được chỉ ra trong các bài viết trên

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

Lưu ý cách classtất cả các tên User, nhưng ở các namespaces khác nhau . Trích dẫn PEP-20: Zen of Python :

Không gian tên là một trong những ý tưởng tuyệt vời - hãy làm nhiều hơn nữa!

Hi vọng điêu nay co ich


2
mọi khi, trừ khi bạn không thể: lớp EG kín
Mikus

nhưng điều đó sẽ không hoạt động trong nhiều trường hợp. ví dụ: public class MyList: List {} - nếu sau này bạn thử MyList xyz = something.ToList (); bạn sẽ gặp khó khăn.
Ưu đãi

@Offler Bạn có thể (và có lẽ nên) sử dụng newtừ khóa cho các phương pháp như vậy hoặc thậm chí tạo ra các ExtensionMethods của riêng bạn, phải không? Trong mọi trường hợp, ý kiến ​​mạnh mẽ của tôi là bạn nên luôn sử dụng các lớp Bộ sưu tập vani (tức là Từ điển, Danh sách, IEnumerable, IQueryable, v.v.) với Mô hình / ViewModels / POCO tùy chỉnh. Như Mvc đã tuyên bố: Công ước về cấu hình
percebus

@percebus không hoạt động trong mọi trường hợp. Tôi cố gắng chuyển đổi các phần Code whre cổ điển sử dụng một api không còn được hỗ trợ sang một api mới hơn. mã chuyển đổi durign sẽ được thay đổi bởi những người khác và vẫn có thể chạy được - vì vậy cả hai đều có thể sử dụng được ngay bây giờ. Việc che giấu Những thứ trên 700.000 LOC (không có bình luận) và vẫn để nó có thể chạy được sẽ dễ dàng hơn, nếu bí danh kiểu c ++ có thể thực hiện được - và bạn chỉ cần một vị trí trong tệp để thay thế một lớp bí danh với việc triển khai từ một trong hai.
Ưu đãi vào

ĐĂNG LẠI để CHỈNH SỬA @Offler Đối với những gì bạn đang mô tả âm thanh mà bạn cần một số chỉnh sửa như Nhà máy có giao diện. IColorScheme oColorScheme = ColorSchemeFactory.Create(); Ngoài ra, bạn có thể muốn xem xét Dependency Injection
percebus

2

Có thể chuyển sang sử dụng giao diện không?

Có lẽ bạn có thể tạo một IColorSchemegiao diện mà tất cả các lớp đều triển khai?

Điều này sẽ hoạt động tốt với mô hình nhà máy như được thể hiện bởi Chris Marasti-Georg


Nó có thể được, nhưng tôi sẽ không dành thời gian cho nó nữa thay vì đổi tên lớp là bảng màu "hiện tại" để sử dụng.
Ian Boyd

0

Đó là một câu trả lời từng phần rất muộn - nhưng nếu bạn xác định cùng một lớp 'ColorScheme', trong cùng một không gian tên 'Outlook', nhưng trong các hội đồng riêng biệt, một tổ hợp được gọi là Outlook2003 và Outlook2007 khác, thì tất cả những gì bạn cần làm là tham khảo hội đồng thích hợp .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.