ชื่อของวัตถุประสงค์คืออะไร?


263

เวอร์ชั่น 6.0 มีคุณสมบัติใหม่nameofแต่ฉันไม่เข้าใจวัตถุประสงค์ของมันเพราะใช้ชื่อตัวแปรและเปลี่ยนเป็นสตริงในการคอมไพล์

ฉันคิดว่ามันอาจมีจุดประสงค์บางอย่างเมื่อใช้งาน<T>แต่เมื่อฉันลองnameof(T)มันก็แค่พิมพ์ให้ฉันTแทนที่จะเป็นประเภทที่ใช้แล้ว

มีความคิดเกี่ยวกับวัตถุประสงค์หรือไม่


2
ดูเพิ่มเติมmsdn.microsoft.com/library/dn986596.aspx
Corak

28
ไม่มีทางที่จะได้รับสิ่งนั้นTมาก่อน มีวิธีรับชนิดที่ใช้ก่อนหน้านี้
Jon Hanna

ตอนแรกมันดูเหมือน overkill และฉันก็ยังไม่เห็นเหตุผลที่น่าสนใจที่จะใช้มัน อาจเป็นตัวอย่าง MVC?
Corey Alix

15
มีประโยชน์แน่นอนเมื่อ refactory / nameofเปลี่ยนชื่อชื่อภายใน ยังช่วยป้องกันการพิมพ์ผิด
bvj

4
เอกสารอย่างเป็นทางการของnameofได้ย้ายมาที่นี่แล้ว: docs.microsoft.com/en-us/dotnet/csharp/language-reference/ ...... - นอกจากนี้ยังแสดงกรณีการใช้งานที่สำคัญซึ่งเป็นคำตอบที่ดีสำหรับคำถามนี้
เครื่องหมายของ

คำตอบ:


323

เกี่ยวกับกรณีที่คุณต้องการใช้ชื่อของคุณสมบัติอีกครั้งตัวอย่างเช่นเมื่อโยนข้อยกเว้นตามชื่อคุณสมบัติหรือจัดการPropertyChangedเหตุการณ์ มีหลายกรณีที่คุณต้องการมีชื่อของคุณสมบัติ

นำตัวอย่างนี้:

switch (e.PropertyName)
{
    case nameof(SomeProperty):
    { break; }

    // opposed to
    case "SomeOtherProperty":
    { break; }
}

ในกรณีแรกให้เปลี่ยนชื่อ SomePropertyจะเปลี่ยนชื่อของคุณสมบัติด้วยหรือจะเป็นการรวบรวมที่ผิดพลาด กรณีสุดท้ายไม่ได้

นี่เป็นวิธีที่มีประโยชน์มากในการรวบรวมรหัสของคุณและไม่มีข้อบกพร่อง (เรียงลำดับ)

( บทความที่ดีมากจาก Eric Lippertทำไมinfoofไม่ทำในขณะที่nameofทำ)


1
ฉันเข้าใจประเด็นเพียงแค่เพิ่มตัวแก้ไขที่เปลี่ยนสตริงเมื่อทำการเปลี่ยนชื่อใหม่ไม่แน่ใจว่า VS มีฟังก์ชันการทำงานที่คล้ายกันหรือไม่
Ash Burlaczenko

7
มันมี. แต่ทั้ง Resharper และ VS ไม่สามารถทำงานในโครงการได้ สิ่งนี้ทำ อันที่จริงนี่เป็นทางออกที่ดีกว่า
Patrick Hofman

49
กรณีการใช้งานทั่วไปอีกอย่างหนึ่งคือการกำหนดเส้นทางในการใช้งาน MVC nameofและชื่อของการดำเนินการแทนสตริงที่มีการเข้ารหัสยาก
RJ Cuthbertson

2
@sotn ฉันไม่แน่ใจว่าฉันเข้าใจสิ่งที่คุณถาม ไม่มีอะไรหยุดคุณจากการใช้มันpublic class MyController { public ActionResult Index() { return View(nameof(Index)); } }- และคุณสามารถใช้nameofกับสมาชิกที่ไม่คงที่ (ตัวอย่างเช่นคุณสามารถโทรnameof(MyController.Index)โดยใช้คลาสข้างต้นและมันจะปล่อย "ดัชนี") ดูตัวอย่างได้ที่msdn.microsoft.com/en-us/library/…
RJ Cuthbertson

2
ฉันไม่เห็นสาเหตุที่พิเศษ ชื่อตัวแปรจะเหมือนกันใช่มั้ย ไม่ว่าคุณจะมีอินสแตนซ์หรือไม่ชื่อตัวแปรจะไม่เปลี่ยน @sotn
Patrick Hofman

176

มันมีประโยชน์จริงๆArgumentExceptionและอนุพันธ์:

public string DoSomething(string input) 
{
    if(input == null) 
    {
        throw new ArgumentNullException(nameof(input));
    }
    ...

ตอนนี้ถ้ามีคน refactors ชื่อของ inputพารามิเตอร์ข้อยกเว้นจะถูกปรับปรุงให้ทันสมัยเกินไป

นอกจากนี้ยังมีประโยชน์ในบางสถานที่ซึ่งต้องใช้การสะท้อนก่อนหน้านี้เพื่อรับชื่อคุณสมบัติหรือพารามิเตอร์

ในตัวอย่างของคุณnameof(T)ได้รับชื่อของพารามิเตอร์ประเภท - นี้จะมีประโยชน์เช่นกัน:

throw new ArgumentException(nameof(T), $"Type {typeof(T)} does not support this method.");

การใช้งานอื่นnameofสำหรับ enums - โดยปกติถ้าคุณต้องการชื่อสตริงของ enum ที่คุณใช้.ToString():

enum MyEnum { ... FooBar = 7 ... }

Console.WriteLine(MyEnum.FooBar.ToString());

> "FooBar"

ซึ่งค่อนข้างช้าเนื่องจาก. Net ถือค่า enum (เช่น7) และค้นหาชื่อ ณ เวลารันไทม์

ใช้แทนnameof:

Console.WriteLine(nameof(MyEnum.FooBar))

> "FooBar"

ตอนนี้. Net แทนที่ชื่อ enum ด้วยสตริงในเวลารวบรวม


การใช้งานอื่นมีไว้สำหรับสิ่งที่ชอบINotifyPropertyChangedและการเข้าสู่ระบบ - ในทั้งสองกรณีคุณต้องการชื่อของสมาชิกที่คุณกำลังจะถูกส่งไปยังวิธีอื่น

// Property with notify of change
public int Foo
{
    get { return this.foo; }
    set
    {
        this.foo = value;
        PropertyChanged(this, new PropertyChangedEventArgs(nameof(this.Foo));
    }
}

หรือ...

// Write a log, audit or trace for the method called
void DoSomething(... params ...)
{
    Log(nameof(DoSomething), "Message....");
}

9
และคุณได้เพิ่มคุณสมบัติดีๆอีกอย่างใน: การแก้ไขสตริง!
Patrick Hofman

1
@PatrickHofman และtypeof(T)ซึ่งเป็นอีกชิ้นหนึ่งของน้ำตาลรวบรวมเวลาที่มีประโยชน์ในสถานการณ์ที่คล้ายกัน :-)
คี ธ

1
สิ่งหนึ่งที่ฉันขาดหายไปคือสิ่งที่ชอบ nameofthismethodสิ่งหนึ่งที่ฉันหายไปเป็นสิ่งที่ต้องการคุณสามารถใช้Log.Error($"Error in {nameof(DoSomething)}...")แต่ถ้าคุณคัดลอกวางนี้กับวิธีอื่น ๆ DoSomethingคุณจะไม่เห็นว่ามันยังหมายถึง ดังนั้นในขณะที่มันทำงานได้อย่างสมบูรณ์กับตัวแปรหรือพารามิเตอร์โลคอลเมธอดคือปัญหา
Tim Schmelter

3
คุณรู้หรือไม่ว่า nameOfจะใช้แอ[DisplayName]ททริบิวถ้ามี? สำหรับenumตัวอย่างที่ฉันใช้[DisplayName]บ่อยกับโครงการ MVC
Luke T O'Brien

2
@ AaronLS ใช่มันค่อนข้างพิเศษและไม่ใช่สิ่งที่คุณจะใช้บ่อย อย่างไรก็ตามนั่นthrow newเป็นรูปแบบการต่อต้านแบบอื่นทั้งหมด - ฉันพบว่าใช้มากเกินไปcatchเกินปกติเป็นปัญหาที่พบบ่อยกับผู้พัฒนารุ่นเยาว์เพราะมันรู้สึกเหมือนกำลังแก้ไขปัญหา
Keith

26

อีกกรณีใช้งานที่nameofคุณสมบัติของ C # 6.0 กลายเป็นประโยชน์ - พิจารณาไลบรารีเช่นDapperซึ่งทำให้การดึงข้อมูล DB ง่ายขึ้นมาก ถึงแม้ว่านี่เป็นห้องสมุดที่ยอดเยี่ยมคุณต้อง hardcode ชื่อคุณสมบัติ / เขตข้อมูลภายในแบบสอบถาม สิ่งนี้หมายความว่าถ้าคุณตัดสินใจที่จะเปลี่ยนชื่อพื้นที่ / เขตข้อมูลของคุณมีโอกาสสูงที่คุณจะลืมปรับปรุงแบบสอบถามเพื่อใช้ชื่อเขตข้อมูลใหม่ ด้วยการแก้ไขและnameofคุณลักษณะของสตริงทำให้การบำรุงรักษาและ typesafe กลายเป็นเรื่องง่าย

จากตัวอย่างที่ให้ไว้ในลิงค์

ไม่มีชื่อของ

var dog = connection.Query<Dog>("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid });

กับชื่อของ

var dog = connection.Query<Dog>($"select {nameof(Dog.Age)} = @Age, {nameof(Dog.Id)} = @Id", new { Age = (int?)null, Id = guid });

3
ฉันรัก Dapper และฉันชอบ interporlations สตริง แต่ IMO นี้ดูน่าเกลียดมาก ความเสี่ยงในการแบ่งแบบสอบถามโดยการเปลี่ยนชื่อคอลัมน์มีขนาดเล็กมากเมื่อเทียบกับแบบสอบถามที่น่าเกลียด ตั้งแต่แรกพบฉันบอกว่าฉันชอบเขียนข้อความค้นหา EF LINQ หรือทำตามแบบแผนเช่น [TableName] [ColumnName] ที่ฉันสามารถค้นหา / แทนที่ข้อความค้นหาของฉันได้อย่างง่ายดายเมื่อต้องการ
drizin

@drizin ฉันใช้Dapper FluentMapเพื่อป้องกันข้อสงสัย (และเพื่อแยกข้อกังวล)
mamuesstack

21

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

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

public void DoStuff(object input)
{
    if (input == null)
    {
        throw new ArgumentNullException(nameof(input));
    }
}

นี้เป็นสิ่งที่ดีถ้าผมเปลี่ยนชื่อของตัวแปรรหัสจะทำลายแทนหรือกลับเป็นข้อยกเว้นที่มีข้อความไม่ถูกต้อง


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

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


6
@atikot: แต่ถ้าคุณเปลี่ยนชื่อตัวแปรคอมไพเลอร์จะไม่สังเกตว่าสตริงไม่ตรงอีกต่อไป
หรือผู้ทำแผนที่

1
จริง ๆ แล้วฉันใช้ resharper ซึ่งนำไปสู่การบัญชี แต่ฉันเห็นจุดของคุณ
atikot

4
@atikot ดังนั้นฉัน แต่ Resharper สร้างคำเตือนเท่านั้นไม่ใช่ข้อผิดพลาดของคอมไพเลอร์ มีความแตกต่างระหว่างคำแนะนำที่แน่นอนและดี
Jodrell

1
@atikot และ Resharper ไม่ตรวจสอบข้อความบันทึก
Jodrell

2
@Jodrell: และฉันสงสัยว่ามันไม่ได้ตรวจสอบการใช้งานอื่น ๆ อย่างใดอย่างหนึ่ง - วิธีการเกี่ยวกับการผูก WPF ที่สร้างขึ้นในรหัสหลังOnPropertyChangedวิธีการที่กำหนดเอง(ที่ยอมรับชื่อคุณสมบัติมากกว่าโดยตรงPropertyChangedEventArgs) หรือเรียกร้องให้มองหา สมาชิกหรือพิมพ์?
หรือผู้ทำแผนที่

13

กรณีการใช้งานทั่วไปที่ฉันนึกได้คือเมื่อทำงานกับINotifyPropertyChangedอินเทอร์เฟซ (โดยทั่วไปทุกอย่างที่เกี่ยวข้องกับ WPF และการผูกใช้อินเทอร์เฟซนี้)

ดูตัวอย่างนี้:

public class Model : INotifyPropertyChanged
{
    // From the INotifyPropertyChanged interface
    public event PropertyChangedEventHandler PropertyChanged;

    private string foo;
    public String Foo
    {
        get { return this.foo; }
        set
        {
            this.foo = value;
            // Old code:
            PropertyChanged(this, new PropertyChangedEventArgs("Foo"));

            // New Code:
            PropertyChanged(this, new PropertyChangedEventArgs(nameof(Foo)));           
        }
    }
}

ดังที่คุณเห็นในแบบเก่าเราต้องผ่านสตริงเพื่อระบุว่าทรัพย์สินใดมีการเปลี่ยนแปลง ด้วยnameofเราสามารถใช้ชื่อของคุณสมบัติโดยตรง นี่อาจจะไม่ใช่เรื่องใหญ่อะไร Fooแต่ภาพสิ่งที่เกิดขึ้นเมื่อใครบางคนเปลี่ยนชื่อของทรัพย์สิน เมื่อใช้สตริงการผูกจะหยุดทำงาน แต่คอมไพเลอร์จะไม่เตือนคุณ เมื่อใช้ nameof คุณได้รับการรวบรวมข้อผิดพลาดว่าไม่มีคุณสมบัติ / Fooข้อโต้แย้งที่มีชื่อ

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


5
ในขณะที่วิธีนี้เป็นวิธีที่ถูกต้องวิธีการที่สะดวกกว่า (และแห้ง) คือการใช้แอ[CallerMemberName]ททริบิวในพารามิเตอร์ของวิธีการใหม่ในการเพิ่มกิจกรรมนี้
Drew Noakes

1
ฉันเห็นด้วย CallerMemberName เป็นสิ่งที่ดี แต่เป็นกรณีการใช้งานแยกต่างหากเนื่องจาก (ตามที่คุณพูด) คุณสามารถใช้งานได้ในวิธีการเท่านั้น สำหรับ DRY ฉันไม่แน่ใจว่า[CallerMemberName]string x = nullดีกว่าnameof(Property)หรือเปล่า คุณสามารถพูดได้ว่าชื่อคุณสมบัติถูกใช้สองครั้ง แต่โดยทั่วไปแล้วอาร์กิวเมนต์จะถูกส่งไปยังฟังก์ชัน ไม่ได้มีความหมายอะไรกับ DRY ฉันคิดว่า :)
รอยต.

จริงๆแล้วคุณสามารถใช้มันในคุณสมบัติ พวกเขาเป็นสมาชิกด้วย ประโยชน์ที่ได้รับnameofคือตัวตั้งค่าคุณสมบัติไม่จำเป็นต้องระบุชื่อคุณสมบัติเลยช่วยลดความเป็นไปได้ของการคัดลอก / วางบั๊ก
Drew Noakes

4
เป็นสถานการณ์ที่ 'ดีกว่าด้วยกัน' สำหรับการINotifyPropertyChangedใช้[CallerMemberNameAttribute]อนุญาตให้แจ้งเตือนการเปลี่ยนแปลงได้รับการยกขึ้นอย่างสะอาดจากตัวตั้งค่าคุณสมบัติในขณะที่nameofไวยากรณ์ช่วยให้การแจ้งเตือนการเปลี่ยนแปลงได้รับการยกระดับอย่างสมบูรณ์จากตำแหน่งอื่นในรหัสของคุณ
Andrew Hanlon

9

การใช้งานทั่วไปส่วนใหญ่จะอยู่ในการตรวจสอบความถูกต้องของอินพุตเช่น

//Currently
void Foo(string par) {
   if (par == null) throw new ArgumentNullException("par");
}

//C# 6 nameof
void Foo(string par) {
   if (par == null) throw new ArgumentNullException(nameof(par));
}

ในกรณีแรกถ้าคุณ refactor วิธีการเปลี่ยนตราไว้หุ้นละชื่อพารามิเตอร์ของคุณอาจจะลืมที่จะเปลี่ยนที่อยู่ในArgumentNullException ด้วยชื่อของคุณไม่ต้องกังวลเกี่ยวกับเรื่องนั้น

ดูเพิ่มเติมที่: nameof (C # และการอ้างอิง Visual Basic)


7

โครงการ ASP.NET Core MVC ใช้nameofในAccountController.csและManageController.csด้วยRedirectToActionวิธีการอ้างอิงการกระทำในตัวควบคุม

ตัวอย่าง:

return RedirectToAction(nameof(HomeController.Index), "Home");

สิ่งนี้แปลเป็น:

return RedirectToAction("Index", "Home");

และใช้เวลานำผู้ใช้ไปกับการกระทำ 'ดัชนี' ในตัวควบคุม 'บ้าน' /Home/Indexคือ


ทำไมไม่ไปทั้งหมูและใช้return RedirectToAction(nameof(HomeController.Index), nameof(HomeController).Substring(nameof(HomeController),0,nameof(HomeController).Length-"Controller".Length));?
Suncat2000

@ Suncat2000 เพราะสิ่งหนึ่งที่ทำในการรวบรวมและอื่น ๆ ไม่ได้? :)
Dinerdo

6

ดังที่คนอื่น ๆ ได้ชี้ให้เห็นแล้วnameofโอเปอเรเตอร์จะใส่ชื่อที่องค์ประกอบนั้นได้รับในซอร์สโค้ด

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

static void Main(string[] args)
{
    Console.WriteLine(nameof(args));
    Console.WriteLine("regular text");
}

// striped nops from the listing
IL_0001 ldstr args
IL_0006 call System.Void System.Console::WriteLine(System.String)
IL_000C ldstr regular text
IL_0011 call System.Void System.Console::WriteLine(System.String)
IL_0017 ret

อย่างไรก็ตามนั่นอาจเป็นข้อเสียเปรียบหากคุณวางแผนที่จะทำให้งงงวยซอฟต์แวร์ของคุณ หลังจาก obfuscation สตริงที่ฝังตัวอาจไม่ตรงกับชื่อขององค์ประกอบ กลไกที่พึ่งพาข้อความนี้จะแตก ตัวอย่างสำหรับสิ่งนั้นรวมถึง แต่ไม่ จำกัด เพียง: Reflection, NotifyPropertyChanged ...

การกำหนดชื่อระหว่างรันไทม์นั้นมีค่าใช้จ่ายบ้าง แต่ก็ปลอดภัยสำหรับการทำให้งงงวย หากไม่ทำให้งงงวยไม่จำเป็นต้องมีหรือวางแผนฉันจะแนะนำให้ใช้nameofผู้ประกอบการ


5

พิจารณาว่าคุณใช้ตัวแปรในรหัสของคุณและจำเป็นต้องได้รับชื่อของตัวแปรและสมมติว่าพิมพ์มันคุณควรจะต้องใช้

int myVar = 10;
print("myVar" + " value is " + myVar.toString());

และถ้ามีคน refactors รหัสและใช้ชื่ออื่นสำหรับ "myVar" เขา / เธอจะต้องดูค่าสตริงในรหัสของคุณและ chenge มัน

แต่ถ้าคุณมี

print(nameof(myVar) + " value is " + myVar.toString());

มันจะช่วย refactor โดยอัตโนมัติ!


ฉันหวังว่าจะมีไวยากรณ์ตัวแปรพารามิเตอร์พิเศษซึ่งจะผ่านอาร์เรย์ของ tuples หนึ่งสำหรับแต่ละพารามิเตอร์ที่มีการเป็นตัวแทนรหัสที่มา, the Typeและค่า ซึ่งจะทำให้เป็นไปได้สำหรับการเรียกใช้วิธีการบันทึกรหัสเพื่อกำจัดความซ้ำซ้อนจำนวนมาก
supercat

5

บทความ MSDNแสดงรายการการกำหนดเส้นทาง MVC (ตัวอย่างที่คลิกแนวคิดสำหรับฉันจริงๆ) ท่ามกลางคนอื่น ๆ ย่อหน้าคำอธิบาย (จัดรูปแบบ) อ่าน:

  • เมื่อรายงานข้อผิดพลาดในรหัส
  • เชื่อมโยงลิงค์ model-view-controller (MVC)
  • การยิงเปลี่ยนสถานที่ให้บริการเหตุการณ์ ฯลฯ

คุณมักจะต้องการที่จะ จับชื่อสตริงของวิธีการที่ การใช้ nameof ช่วยให้โค้ดของคุณถูกต้องเมื่อเปลี่ยนชื่อนิยาม

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

คำตอบที่ได้รับการยอมรับ / ติดอันดับนั้นเป็นตัวอย่างที่ยอดเยี่ยมหลายประการ


3

วัตถุประสงค์ของnameofผู้ประกอบการคือการให้ชื่อแหล่งที่มาของสิ่งประดิษฐ์

โดยปกติชื่อแหล่งที่มาจะเป็นชื่อเดียวกับชื่อเมทาดาทา:

public void M(string p)
{
    if (p == null)
    {
        throw new ArgumentNullException(nameof(p));
    }
    ...
}

public int P
{
    get
    {
        return p;
    }
    set
    {
        p = value;
        NotifyPropertyChanged(nameof(P));
    }
}

แต่นี่อาจไม่ใช่กรณี:

using i = System.Int32;
...
Console.WriteLine(nameof(i)); // prints "i"

หรือ:

public static string Extension<T>(this T t)
{
    return nameof(T); returns "T"
}

การใช้งานครั้งเดียวที่ฉันให้ไว้มีไว้เพื่อการตั้งชื่อทรัพยากร:

[Display(
    ResourceType = typeof(Resources),
    Name = nameof(Resources.Title_Name),
    ShortName = nameof(Resources.Title_ShortName),
    Description = nameof(Resources.Title_Description),
    Prompt = nameof(Resources.Title_Prompt))]

ความจริงก็คือในกรณีนี้ฉันไม่ต้องการแม้แต่คุณสมบัติที่สร้างขึ้นเพื่อเข้าถึงทรัพยากร แต่ตอนนี้ฉันมีเวลารวบรวมตรวจสอบว่ามีทรัพยากรอยู่


0

หนึ่งของการใช้งานของnameofคำหลักสำหรับการตั้งค่าBindingใน WPF โปรแกรม

ในการตั้งค่าBindingคุณต้องตั้งค่าPathด้วยสตริงและด้วยnameofคำหลักคุณสามารถใช้ตัวเลือก Refactor ได้

ตัวอย่างเช่นหากคุณมีIsEnableคุณสมบัติการพึ่งพาในของคุณUserControlและคุณต้องการที่จะผูกไว้กับIsEnableของบางอย่างCheckBoxในคุณUserControlคุณสามารถใช้รหัสทั้งสองนี้:

CheckBox chk = new CheckBox();
Binding bnd = new Binding ("IsEnable") { Source = this };
chk.SetBinding(IsEnabledProperty, bnd);

และ

CheckBox chk = new CheckBox();
Binding bnd = new Binding (nameof (IsEnable)) { Source = this };
chk.SetBinding(IsEnabledProperty, bnd);

เห็นได้ชัดว่ารหัสแรกไม่สามารถ refactor ได้ แต่รหัสลับ ...


0

ก่อนหน้านี้เราใช้บางอย่างเช่น:

// Some form.
SetFieldReadOnly( () => Entity.UserName );
...
// Base form.
private void SetFieldReadOnly(Expression<Func<object>> property)
{
    var propName = GetPropNameFromExpr(property);
    SetFieldsReadOnly(propName);
}

private void SetFieldReadOnly(string propertyName)
{
    ...
}

เหตุผล - รวบรวมเวลาปลอดภัย ไม่มีใครสามารถเปลี่ยนชื่อคุณสมบัติและตรรกะการถอดรหัสได้เงียบ ๆ ตอนนี้เราสามารถใช้ nameof ()


0

มันมีข้อดีเมื่อคุณใช้ ASP.Net MVC เมื่อคุณใช้ตัวช่วย HTML เพื่อสร้างตัวควบคุมในมุมมองจะใช้ชื่อคุณสมบัติในชื่อ attribure ของอินพุต html:

@Html.TextBoxFor(m => m.CanBeRenamed)

มันทำให้อะไรเช่นนั้น:

<input type="text" name="CanBeRenamed" />

ดังนั้นตอนนี้ถ้าคุณต้องการตรวจสอบความถูกต้องของคุณสมบัติของคุณในวิธีการตรวจสอบคุณสามารถทำได้:

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
  if (IsNotValid(CanBeRenamed)) {
    yield return new ValidationResult(
      $"Property {nameof(CanBeRenamed)} is not valid",
      new [] { $"{nameof(CanBeRenamed)}" })
  }
}

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


0

อีกกรณีการใช้งานของnameofคือการตรวจสอบหน้าแท็บแทนการตรวจสอบดัชนีคุณสามารถตรวจสอบNameคุณสมบัติของแท็บเพจดังต่อไปนี้:

if(tabControl.SelectedTab.Name == nameof(tabSettings))
{
    // Do something
}

ยุ่งน้อยลง :)


0

ฉันพบว่าnameofเพิ่มความสามารถในการอ่านคำสั่ง SQL ที่ยาวและซับซ้อนในแอปพลิเคชันของฉัน มันทำให้ตัวแปรโดดเด่นกว่าทะเลของสตริงนั้นและกำจัดงานของคุณในการหาว่าตัวแปรที่ใช้ในงบ SQL ของคุณ

public bool IsFooAFoo(string foo, string bar)
{
    var aVeryLongAndComplexQuery = $@"SELECT yada, yada
    -- long query in here
    WHERE fooColumn = @{nameof(foo)}
    AND barColumn = @{nameof(bar)}
    -- long query here";


    SqlParameter[] parameters = {
        new SqlParameter(nameof(foo), SqlDBType.VarChar, 10){ Value = foo },
        new SqlParameter(nameof(bar), SqlDBType.VarChar, 10){ Value = bar },
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.