ชื่อแทนเนมสเปซ C # - ประเด็นคืออะไร?


97

ใครจะใช้นามแฝงเนมสเปซเช่น

 using someOtherName =  System.Timers.Timer;

สำหรับฉันดูเหมือนว่ามันจะเพิ่มความสับสนให้กับการเข้าใจภาษามากขึ้น


6
แล้วระบบกว้างusing int = System.Int32ใน C # ล่ะ? มีประโยชน์ไม่ใช่เหรอ? การใช้งานแบบเดียวกับที่สามารถใช้ประโยชน์จากที่อื่นได้
nawfal

@nawfal ฉันเชื่อว่านามแฝงประเภทไม่สามารถส่งออกได้ หมายความว่าคุณไม่สามารถกำหนดสิ่งที่ต้องการusing int = System.Int32และใช้ในที่อื่นนอกเหนือจากไฟล์ประกาศ ดังนั้นสิ่งนี้intกับInt32นามแฝงอาจทำได้โดยวิธีอื่นหรือเป็นสิ่งพิเศษในคอมไพเลอร์ / รันไทม์
KFL

1
@KFL นั้นเป็นความจริง แต่ประโยชน์ทั้งสองอย่างนั้นมีลักษณะเดียวกัน
nawfal

1
@nawfal ข้อโต้แย้งของคุณเกี่ยวกับusing int = System.Int32ทั้งผิดและทำให้เข้าใจผิด - ผิดเพราะintไม่ได้ใช้นามแฝงตามที่คุณอธิบายไว้ มันเป็นความเข้าใจผิดเพราะคุณบ่งบอกถึงประเภทนามแฝงสามารถนำมาใช้ทั่วโลกเช่นเดียวกับวิธีการที่จะใช้มากกว่าint Int32
KFL

2
@KFL ฉันไม่ได้หมายถึงทั้งสองอย่าง ฉันเพิ่งระบุว่าทำไมการมีชื่อที่กำหนดเองสำหรับประเภทจึงมีประโยชน์
nawfal

คำตอบ:


153

นั่นคือนามแฝงประเภทไม่ใช่นามแฝงเนมสเปซ มันมีประโยชน์ในการทำให้สับสน - ตัวอย่างเช่นต่อต้าน:

using WinformTimer = System.Windows.Forms.Timer;
using ThreadingTimer = System.Threading.Timer;

(ps: ขอบคุณที่เลือกTimer;-p)

มิฉะนั้นหากคุณใช้ทั้งสองไฟล์System.Windows.Forms.TimerและSystem.Timers.Timerในไฟล์เดียวกันคุณจะต้องตั้งชื่อเต็ม (เพราะTimerอาจทำให้สับสนได้)

นอกจากนี้ยังมีส่วนร่วมกับexternนามแฝงสำหรับการใช้ประเภทที่มีชื่อประเภทที่มีคุณสมบัติครบถ้วนเหมือนกันจากแอสเซมบลีที่แตกต่างกันซึ่งหายาก แต่มีประโยชน์ที่จะได้รับการสนับสนุน


จริงๆแล้วฉันสามารถดูการใช้งานอื่นได้: เมื่อคุณต้องการเข้าถึงประเภทอย่างรวดเร็ว แต่ไม่ต้องการใช้แบบปกติusingเพราะคุณไม่สามารถนำเข้าวิธีการขยายที่ขัดแย้งกันได้ ... ค่อนข้างซับซ้อน แต่ ... นี่คือตัวอย่าง ...

namespace RealCode {
    //using Foo; // can't use this - it breaks DoSomething
    using Handy = Foo.Handy;
    using Bar;
    static class Program {
        static void Main() {
            Handy h = new Handy(); // prove available
            string test = "abc";            
            test.DoSomething(); // prove available
        }
    }
}
namespace Foo {
    static class TypeOne {
        public static void DoSomething(this string value) { }
    }
    class Handy {}
}
namespace Bar {
    static class TypeTwo {
        public static void DoSomething(this string value) { }
    }
}

8
สามารถใช้แทนเนมสเปซหรือพิมพ์ชื่อ
Sean Bright

1
@Sean: ใช่ แต่ตัวอย่างที่ให้คือประเภท
Marc Gravell

@lupefiasco: เลือก OP ได้สะดวกSystem.Timers.Timer;-p
Marc Gravell

อาคิดว่าคุณอ้างถึงแนวคิดไม่ใช่ตัวอย่างเฉพาะ Mea culpa
Sean Bright

26

ฉันใช้มันเมื่อฉันมีหลายเนมสเปซที่มีเนมสเปซย่อยและ / หรือชื่ออ็อบเจ็กต์ที่ขัดแย้งกันซึ่งคุณสามารถทำบางสิ่งเช่น [ดังตัวอย่าง]:

using src = Namespace1.Subspace.DataAccessObjects;
using dst = Namespace2.Subspace.DataAccessObjects;

...

src.DataObject source = new src.DataObject();
dst.DataObject destination = new dst.DataObject();

ซึ่งจะต้องเขียน:

Namespace1.Subspace.DataAccessObjects.DataObject source = 
  new Namespace1.Subspace.DataAccessObjects.DataObject();

Namespace2.Subspace.DataAccessObjects.DataObject dstination = 
  new Namespace2.Subspace.DataAccessObjects.DataObject();

ช่วยประหยัดการพิมพ์จำนวนมากและสามารถใช้เพื่อทำให้โค้ดอ่านง่ายขึ้นมาก


17

นอกเหนือจากตัวอย่างที่กล่าวถึงแล้วการพิมพ์นามแฝง (แทนที่จะเป็นนามแฝงเนมสเปซ) ยังมีประโยชน์เมื่ออ้างถึงประเภททั่วไปซ้ำ ๆ :

Dictionary<string, SomeClassWithALongName> foo = new Dictionary<string, SomeClassWithALongName>();

private void DoStuff(Dictionary<string, SomeClassWithALongName> dict) {}

เทียบกับ:

using FooDict = Dictionary<string, SomeClassWithALongName>;

FooDict foo = new FooDict();

private void DoStuff(FooDict dict) {}

8

ความกะทัดรัด

มีประโยชน์มากมายในการให้ความชัดเจนระหว่างเนมสเปซที่ใช้ชื่อประเภทร่วมกัน แต่โดยพื้นฐานแล้วมันเป็นแค่น้ำตาล


มันแสดงให้เห็นอย่างชัดเจนว่าคุณกำลังใช้สัญลักษณ์ใด ไม่ใช่แค่น้ำตาล แต่เป็นเพียงเล็กน้อย (ถ้าคุณไม่ต้องการกำหนดชื่อใหม่)
Earth Engine

7

ฉันมักจะใช้มันในสถานการณ์เช่นนี้

using Utility = MyBaseNamespace.MySubNamsepace.Utility;

โดยที่Utilityจะมีบริบทที่แตกต่างออกไป (เช่นMyBaseNamespace.MySubNamespace.MySubSubNamespace.Utility) แต่ฉันคาดหวัง / ชอบUtilityที่จะชี้ไปที่คลาสนั้น ๆ เสมอ


6

จะมีประโยชน์มากเมื่อคุณมีหลายคลาสที่มีชื่อเดียวกันในหลาย ๆ เนมสเปซที่รวมไว้ ตัวอย่างเช่น...

namespace Something.From.SomeCompanyA {
    public class Foo {
        /* ... */
    }
}

namespace CompanyB.Makes.ThisOne {
    public class Foo {
        /* ... */
    }
}

คุณสามารถใช้นามแฝงเพื่อทำให้คอมไพเลอร์พอใจและทำให้สิ่งต่างๆชัดเจนยิ่งขึ้นสำหรับคุณและคนอื่น ๆ ในทีมของคุณ:

using CompanyA = Something.From.CompanyA;
using CompanyB = CompanyB.Makes.ThisOne;

/* ... */

CompanyA.Foo f = new CompanyA.Foo();
CompanyB.Foo x = new CompanyB.Foo();

3

เราได้กำหนดนามแฝงเนมสเปซสำหรับเนมสเปซทั้งหมดของเรา สิ่งนี้ทำให้ง่ายต่อการดูว่าคลาสมาจากไหนเช่น:

using System.Web.WebControls;
// lots of other using statements

// contains the domain model for project X
using dom = Company.ProjectX.DomainModel; 
// contains common web functionality
using web = Company.Web;
// etc.

และ

// User from the domain model
dom.User user = new dom.User(); 
// Data transfer object
dto.User user = new dto.User(); 
// a global helper class
utl.SomeHelper.StaticMethod(); 
// a hyperlink with custom functionality
// (as opposed to System.Web.Controls.HyperLink)
web.HyperLink link = new web.HyperLink(); 

เราได้กำหนดแนวทางบางประการว่าจะต้องตั้งชื่อนามแฝงอย่างไรและทุกคนใช้มัน


1
คุณไม่พบว่าบ่อยครั้งที่นามแฝงเกี่ยวข้องกับบริบทที่ใช้มากกว่าตำแหน่งทางกายภาพของวัตถุหรือไม่?
BenAlabaster

2

ฉันพบว่านามแฝงมีประโยชน์มากในการทดสอบหน่วย เมื่อคุณเขียนแบบทดสอบหน่วยการเรียนรู้เรื่องที่จะทดสอบเป็นเรื่องปกติ

MyClass myClassUT;

เป็นmyClassUTหัวเรื่องU nder T est แต่ถ้าคุณต้องการเขียนการทดสอบหน่วยสำหรับคลาสคงที่ด้วยวิธีการคงที่ล่ะ? จากนั้นคุณสามารถสร้างนามแฝงดังนี้:

using MyStaticClassUT = Namespace.MyStaticClass;

จากนั้นคุณสามารถเขียนการทดสอบหน่วยของคุณได้ดังนี้:

public void Test()
{
    var actual = MyStaticClassUT.Method();
    var expected = ...
}

และคุณไม่เคยมองเห็นสิ่งที่ถูกทดสอบ


2

ในทางหนึ่งมันมีประโยชน์มากในขณะที่เขียนโค้ดใน Visual Studio

กรณีการใช้งาน : สมมติว่าผมจะใช้เรียนเพียงไม่กี่เช่นจากใน namespaceSqlConnection System.Dataตามปกติฉันจะนำเข้าSystem.Data.SqlClientเนมสเปซที่ด้านบนของไฟล์ * .cs ดังที่แสดงด้านล่าง:

using System.Data;

ตอนนี้ดู Intellisense ของฉัน มีการแพร่หลายอย่างมากโดยมีคลาสมากมายให้เลือกในขณะที่พิมพ์ในโปรแกรมแก้ไขโค้ด ฉันจะไม่ใช้คลาสทั้งหมดเลย:

ป้อนคำอธิบายภาพที่นี่

ดังนั้นฉันจึงอยากใช้นามแฝงที่ด้านบนของไฟล์ * .cs ของฉันและรับมุมมอง Intellisense ที่ชัดเจน:

using SqlDataCon = System.Data.SqlClient.SqlConnection

ตอนนี้ดูที่มุมมอง Intellisense ของฉัน มีความใสและสะอาดเป็นพิเศษ

ป้อนคำอธิบายภาพที่นี่


1

เหตุผลหนึ่งที่ฉันรู้ ช่วยให้คุณใช้ชื่อที่สั้นลงเมื่อคุณมีการชนชื่อจากเนมสเปซที่นำเข้า ตัวอย่าง:

หากคุณประกาศusing System.Windows.Forms;และ using System.Windows.Input; อยู่ในไฟล์เดียวกันเมื่อคุณไปที่การเข้าถึงModifierKeysคุณอาจพบว่าชื่อModifierKeysนั้นอยู่ในทั้งในSystem.Windows.Forms.ControlและSystem.Windows.Inputเนมสเปซ ดังนั้นด้วยการประกาศusing Input = System.Windows.Input;แล้วคุณจะได้รับผ่านทางSystem.Windows.Input.ModifierKeysInput.ModifierKeys

ฉันไม่ใช่บัฟ C # แต่การใช้นามแฝงเนมสเปซดูเหมือน "แนวทางปฏิบัติที่ดีที่สุด" สำหรับฉัน ด้วยวิธีนี้คุณจะรู้ว่าคุณได้รับอะไรและยังไม่ต้องพิมพ์มากเกินไป


1

คุณสามารถใช้เพื่อแก้ไขโค้ดได้อย่างง่ายดาย

ตัวอย่างเช่น:

#if USE_DOUBLES
using BNumber = System.Double;
#else
using BNumber = System.Single;
#endif

public void BNumber DoStuff(BNumber n) {
    // ...
}
public void BNumber DoStuff2(BNumber n) {
    // ...
}
public void BNumber DoStuff3(BNumber n) {
    // ...
}

ด้วยการเปลี่ยนแปลงคำสั่งง่ายๆคุณสามารถตัดสินใจได้ว่ารหัสทั้งหมดของคุณใช้งานได้floatหรือdoubleไม่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.