ทำความเข้าใจกับ setters ส่วนตัว


94

ฉันไม่เข้าใจความจำเป็นของการมีตัวตั้งค่าส่วนตัวซึ่งเริ่มต้นด้วย C # 2

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

สิ่งนี้สำหรับฉันคือการใช้ "การห่อหุ้ม" มีข้อโต้แย้งบางประการที่อ้างว่าตัวตั้งค่าส่วนตัวจะอนุญาตให้คุณใช้การห่อหุ้ม

ฉันไม่ได้ใช้การห่อหุ้มโดยใช้วิธีการตั้งค่าสาธารณะหรือไม่? ทำไมเราถึงต้องการตัวตั้งค่าส่วนตัว?

อะไรคือความแตกต่างระหว่างคลาสที่ไม่เปลี่ยนรูปและคลาสที่มีตัวตั้งค่าส่วนตัว?


1
ฉันชอบเซ็ตเตอร์ส่วนตัวครั้งใหญ่ - ช่วยฉันจัดชั้นเรียนที่น่าเกลียดอีกครั้ง พวกเขายังทำให้มันเป็นไปไม่ได้ที่จะประกาศและกำหนดตัวแปรเช่นไม่ใช่อย่างต่อเนื่องในครั้งเดียวเช่นดังนั้น: แล้วในหนึ่งในการก่อสร้าง:private File settingsFile = null; if (settingsFile == null) { settingsFile = GetSettingsFile() };การรีแฟคโค้ดแบบนั้นทำให้บางครั้งฉันร้องไห้ :) เพียงเพราะคุณสามารถตั้งค่าสมาชิกก่อนตัวสร้างได้ไม่ได้หมายความว่าคุณควรมีตัวสร้างหลายตัวสิ่งนี้ทำให้ยากที่จะทำตามตรรกะ ตัวตั้งค่าส่วนตัวบังคับให้คุณกำหนดค่าภายในตัวสร้างหรือใหม่กว่า
Hamish Grubijan

คำตอบ:


272

อย่างมีเหตุผล

การมีตัวตั้งค่าส่วนตัวเป็นเพราะคุณสามารถใช้คุณสมบัติอัตโนมัติ:

public int MyProperty { get; set; }

คุณจะทำอย่างไรถ้าต้องการให้อ่านอย่างเดียว

public int MyProperty { get; }

โอ้ยย !! ฉันไม่สามารถเข้าถึงได้จากชั้นเรียนของฉันเอง ฉันควรสร้างมันให้เหมือนคุณสมบัติทั่วไป:

private int myProperty;
public int MyProperty { get { return myProperty; } }

อืม ... แต่ฉันทำคุณสมบัติ "Auto Property" หาย ...

public int MyProperty { get; private set; }

AHHH .. ดีกว่า !!


1
ขอบคุณ. สิ่งนี้สมเหตุสมผลอีกครั้ง
Dene

4
@ktutnik ขอบคุณที่อธิบายสิ่งนี้ในแบบที่คุณทำ มันก็สมเหตุสมผลสำหรับฉันเช่นกันตอนนี้!
Vivek M. Chawla

4
คำตอบที่มีภาพประกอบดีเยี่ยม
imnk

3
Oh crap!! I can't access it from my own classการเริ่มต้น C # 6.0 นี่เป็นเพียงภายนอกระยะเริ่มต้นจริงเท่านั้น ดูคำตอบของฉันstackoverflow.com/a/34223746/198797
tsemer

1
เพิ่มคำตอบ # tsemer ด้วย C # 6 จะไม่เทียบเท่ากับ{get; } { get; private set; }สำหรับวิธีแรกproperty.GetSetMethod(true)ผลตอบแทนและหลังnull trueสิ่งนี้ทำให้ฉันประหลาดใจ
emragins

38

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

ดังนั้น:

public int MyProperty
{
    get; private set;
}

เหมือนกับ:

private int myProperty;
public int MyProperty
{
    get { return myProperty; }
}

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

เพื่อตอบคำถามสุดท้ายของคุณ MSDN ได้กล่าวไว้กับผู้ตั้งค่าส่วนตัว:

อย่างไรก็ตามสำหรับคลาสขนาดเล็กหรือโครงสร้างที่ห่อหุ้มชุดของค่า (ข้อมูล) และมีพฤติกรรมเพียงเล็กน้อยหรือไม่มีเลยขอแนะนำให้ทำให้อ็อบเจ็กต์ไม่เปลี่ยนรูปโดยการประกาศ set accessor เป็นไพรเวต

จากหน้า MSDN ในคุณสมบัติ Auto Implemented


1
ขออภัยที่ยังไม่เห็นมูลค่าเพิ่มเนื่องจากมีตัวตั้งค่าส่วนตัว ถ้าเราไม่ต้องการให้ setter เปิดเผยเราก็มี แต่ getter หากเราต้องการเพิ่มตัวตรวจสอบเราสามารถมีตัวตั้งค่าสาธารณะและเพิ่มการตรวจสอบความถูกต้องได้ ทำไมเราต้องมี setter ที่ไม่สามารถเข้าถึงได้? วิธีที่ฉันเข้าใจก็คือ "ใช้รถคันนี้ แต่คุณขับไม่ได้" ทำไมคุณถึงต้องการให้รถฉันถ้าฉันจะไม่ขับมันต่อไป
Dene

@ ดีเน - คุณทำได้แน่นอนเพราะมันไม่ผิด การมีคุณสมบัติที่ใช้งานอัตโนมัติไม่ได้บังคับ
ChrisF

ฉันรู้ว่าไม่มีอะไรผิดในการทำตามวิธีที่ฉันแสดงออกมา มันเป็นเพียงสำหรับฉันที่จะชื่นชมการแสดงโดย C # 2 ดูเหมือนว่าจะมีการโฆษณามากมายอยู่รอบตัว แต่ฉันรู้สึกไม่ได้หรือเห็นคุณค่า
Dene

@ เดเน่ฉันพลาดทุกโฆษณาเกี่ยวกับเรื่องนี้ แต่ในที่สุดเมื่อฉันเห็นว่ามันทำได้ฉันก็มีความสุขเพราะฉันรู้วิธีทำความสะอาดคลาสยาว ๆ จากยุค. Net 1.1 แม้ว่าคุณจะสามารถใช้ค่าของคุณสมบัติที่ยังไม่ได้ตั้งค่า แต่การทำเช่นนั้นจะน้อยกว่าการใช้ค่าของตัวแปรสมาชิกอินสแตนซ์ที่ตั้งค่าเป็น null
Hamish Grubijan

ทำให้โค้ดง่ายขึ้น เช่นเดียวกับคุณสมบัติของรถยนต์ การอัปเดต C # ที่ตามมาหลายรายการเกี่ยวกับการทำให้โค้ดสั้นลงและอ่านได้ คุณยังคงสามารถทำสิ่งอื่น ๆ ได้หากต้องการ - ความเข้ากันได้แบบย้อนกลับดูเหมือนจะเป็นจุดมุ่งหมายที่ยิ่งใหญ่ ฉันเดาว่ามันเป็นเรื่องของรสนิยม
niico

18

มันค่อนข้างง่าย ตัวตั้งค่าส่วนตัวอนุญาตให้คุณสร้างคุณสมบัติสาธารณะหรือที่มีการป้องกันแบบอ่านอย่างเดียว

แค่นั้นแหละ. นั่นเป็นเหตุผลเดียว

ใช่คุณสามารถสร้างคุณสมบัติแบบอ่านอย่างเดียวได้โดยระบุเฉพาะ getter แต่ด้วยคุณสมบัติที่ถูกฝังโดยอัตโนมัติคุณจะต้องระบุทั้ง get และ set ดังนั้นหากคุณต้องการให้คุณสมบัติที่ใช้งานอัตโนมัติเป็นแบบอ่านอย่างเดียวคุณต้องใช้ setters ส่วนตัว ไม่มีวิธีอื่นที่จะทำได้

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


2
ขอบคุณ "หากคุณต้องการให้คุณสมบัติที่ติดตั้งอัตโนมัติเป็นแบบอ่านอย่างเดียวคุณต้องใช้ตัวตั้งค่าส่วนตัว" สิ่งนี้สมเหตุสมผลสำหรับฉัน
Dene

18

ด้วยการแนะนำC # 6.0และไวยากรณ์สำหรับAuto-Property Initializers ตัวตั้งค่าส่วนตัวไม่จำเป็นอีกต่อไปสำหรับคุณสมบัติที่ตั้งค่าเมื่อเริ่มต้นไม่ว่าจะเป็นแบบอินไลน์หรือภายในตัวสร้าง

ตอนนี้ไวยากรณ์ใหม่เหล่านี้รวบรวม:

คุณสมบัติเริ่มต้นแบบอินไลน์

public class MyClass1 {
  public string MyProperty { get; } = "Aloha!"
}

ตัวสร้างเริ่มต้นคุณสมบัติ

public class MyClass2 {
  public string MyProperty { get; }

  public MyClass2(string myProperty) {
    MyProperty = myProperty;
  }
}

3
@ Ziggler แน่นอนมันไม่ได้ OP ไม่ถามเลย เขาไม่เข้าใจความจำเป็นของการมีพวกเขา คำตอบนี้: "คุณไม่จำเป็นต้องมีอีกต่อไปในสถานการณ์นี้"
tsemer

6

ฉันไม่เข้าใจความจำเป็นของการมีตัวตั้งค่าส่วนตัวซึ่งเริ่มต้นด้วย C # 2

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


public class Item
{
  public string item_code;
  public int qty;

  public Item(string i, int q)
  {
    this.item_code = i;
    this.qty = q;
  }
}

public class Invoice
{
  public List Items { get; private set; }

  public Invoice()
  {
    this.Items = new List();
  }
}

public class TestInvoice
{
  public void Test()
  {
    Invoice inv = new Invoice();
    inv.Items.Add(new Item("apple", 10));

    List my_items = new List();
    my_items.Add(new Item("apple", 10));

    inv.Items = my_items;   // compilation error here.
  }
}

+1 สำหรับการเน้นว่าคุณสมบัตินั้นสามารถจัดการได้ผ่านทาง getter สาธารณะแม้ว่าจะมีตัวตั้งค่าส่วนตัวก็ตาม
user1725145

4

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

ในกรณีนี้คุณสามารถสร้างวิธีการคำนวณของคุณได้

private void Calculate(int value)
{
 //...
}

หรือคุณสามารถทำได้โดยใช้

public int MyProperty {get; private set;}

ในกรณีเหล่านี้ฉันขอแนะนำให้ใช้ในภายหลังเนื่องจากคุณสมบัติ refactor แต่ละองค์ประกอบของสมาชิกยังคงอยู่

นอกจากนั้นหากยังบอกว่าคุณแมปคุณสมบัติด้วยตัวแปร ในกรณีนี้ภายในโค้ดของคุณคุณต้องการเขียนดังนี้:

public int myprop;
public int MyProperty {get { return myprop;}}

... ...

this.myprop = 30;

... ...
if(this.MyProperty > 5)
   this.myprop = 40;

โค้ดด้านบนดูน่ากลัวเนื่องจากโปรแกรมเมอร์ต้องใช้ความระมัดระวังในการใช้ MyProperty for Get และ myprop for Set

Rether เพื่อความสม่ำเสมอคุณสามารถใช้ตัวตั้งค่าส่วนตัวซึ่งทำให้ Propoerty อ่านอย่างเดียวภายนอกในขณะที่คุณสามารถใช้ตัวตั้งค่าภายในรหัสของคุณได้


3

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


2

การห่อหุ้มหมายความว่าสถานะของวัตถุเกิดขึ้นผ่านอินเทอร์เฟซที่กำหนดไว้เท่านั้นและด้วยเหตุนี้คลาสจึงสามารถตรวจสอบให้แน่ใจว่าสถานะนี้ถูกต้องเสมอและสอดคล้องกับวัตถุประสงค์ของคลาส

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

แม้ว่ากรณีเหล่านี้ส่วนใหญ่จะ จำกัด เฉพาะคลาสที่ส่วนใหญ่เป็น "ข้อมูลเก่าธรรมดา" พวกเขายังไม่น่าสนใจในเรื่องนี้มากพอเกี่ยวกับพวกเขา

ในอีกกรณีหนึ่งในภาษาอื่นจะมีเมธอด getter และ setter บางอย่างเช่นint getId()เพื่อรับค่าและvoid setId(int val)อัปเดต

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

(อันที่จริงเนื่องจากวิธีการทำงานของการสะท้อนกลับและกรณีต่างๆเช่นDataBinder.Evalการมีคุณสมบัตินั้นมีประโยชน์แม้ว่าเขตข้อมูลจะทำงานได้ดี แต่นั่นก็เป็นอีกเรื่องหนึ่ง)

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

การห่อหุ้มไม่ใช่เรื่องสำคัญว่าตัวตั้งค่า (หรือตัวรับ) ของคุณเป็นแบบสาธารณะส่วนตัวได้รับการคุ้มครองหรือภายใน แต่ขึ้นอยู่กับว่าเหมาะสมหรือไม่ เริ่มต้นด้วยการเริ่มต้นของทุกสาขาเป็นส่วนตัว (และสำหรับเรื่องที่readonly) แล้วในฐานะสมาชิกเพิ่มที่จำเป็น (ไม่ว่าคุณสมบัติหรือวิธีการ) ที่แก้ไขเขตข้อมูลเหล่านั้นและให้แน่ใจว่าวัตถุที่ยังคงถูกต้องตามที่พวกเขาเปลี่ยนแปลง สิ่งนี้ทำให้มั่นใจได้ว่าค่าคงที่ของคลาสจะถูกเก็บไว้ซึ่งหมายความว่ากฎที่อธิบายถึงชุดของสถานะที่ถูกต้องที่สามารถอยู่ได้นั้นจะไม่มีวันแตกหัก (ตัวสร้างยังช่วยโดยการตรวจสอบให้แน่ใจว่าเริ่มต้นในสถานะที่ถูกต้องเช่นนั้น)

สำหรับคำถามสุดท้ายของคุณการไม่เปลี่ยนรูปหมายความว่าคลาสนั้นไม่มีตัวตั้งค่าสาธารณะที่ได้รับการป้องกันหรือภายในและไม่มีวิธีสาธารณะที่ได้รับการป้องกันหรือภายในที่เปลี่ยนแปลงฟิลด์ มีองศานี้ใน C # มีสามองศาที่เป็นไปได้:

  1. ฟิลด์อินสแตนซ์ของคลาสทั้งหมดเป็นreadonlyดังนั้นแม้แต่รหัสส่วนตัวก็ไม่สามารถแก้ไขได้ รับประกันว่าจะไม่เปลี่ยนรูป (สิ่งใดก็ตามที่พยายามเปลี่ยนแปลงจะไม่รวบรวม) และการเพิ่มประสิทธิภาพอาจทำได้ที่ด้านหลังของสิ่งนี้

  2. ชั้นเรียนไม่สามารถเปลี่ยนรูปได้จากภายนอกเนื่องจากไม่มีสมาชิกสาธารณะเปลี่ยนแปลงอะไร แต่ไม่รับประกันว่าreadonlyจะไม่เปลี่ยนจากภายใน

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


1

คุณต้องมีตัวตั้งค่าส่วนตัวหากคุณต้องการสนับสนุนสถานการณ์ต่อไปนี้ (ไม่เพียง แต่สำหรับสิ่งนี้ แต่ควรชี้ให้เห็นเหตุผลที่ดีประการหนึ่ง): คุณมีคุณสมบัติที่อ่านได้อย่างเดียวในชั้นเรียนของคุณนั่นคือเฉพาะคลาสเท่านั้นที่ได้รับอนุญาตให้เปลี่ยนแปลง แต่อาจเปลี่ยนแปลงได้หลังจากสร้างอินสแตนซ์ สำหรับการผูกคุณจะต้องเริ่มการทำงาน PropertyChanged-event ควรทำสิ่งนี้ในตัวตั้งค่าคุณสมบัติ (ส่วนตัว) อันที่จริงคุณสามารถเริ่มเหตุการณ์ PropertyChanged จากที่อื่นในชั้นเรียนได้ แต่การใช้ตัวตั้งค่าส่วนตัวสำหรับสิ่งนี้คือ "ความเป็นพลเมืองที่ดี" เนื่องจากคุณไม่ได้แจกจ่ายทริกเกอร์การเปลี่ยนแปลงคุณสมบัติของคุณไปทั่วชั้นเรียนของคุณ แต่เก็บไว้ที่ ทรัพย์สินที่เป็นของ


1

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

คลาสที่ไม่เปลี่ยนรูปเป็นคลาสที่ไม่เปลี่ยนแปลงเมื่อสร้างขึ้นแล้วดังนั้นจึงจำเป็นต้องมีตัวตั้งค่าส่วนตัว (หรือไม่มีตัวตั้งเลย) เพื่อปกป้องคุณสมบัติ

ตัวตั้งค่าส่วนตัวเข้ามาใช้บ่อยขึ้นโดยใช้ชวเลขคุณสมบัติที่ติดตั้งใน C # 3 ใน C # 2 ตัวเซ็ตมักจะถูกละไว้และข้อมูลส่วนตัวจะเข้าถึงได้โดยตรงเมื่อตั้งค่า

คุณสมบัตินี้:

public int Size { get; private set; }

เหมือนกับ:

private int _size;
public int Size {
  get { return _size; }
  private set { _size = value; }
}

ยกเว้นชื่อของตัวแปรสำรองถูกสร้างขึ้นภายในโดยคอมไพเลอร์ดังนั้นคุณจึงไม่สามารถเข้าถึงได้โดยตรง

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


ถ้าฉันจำได้อย่างถูกต้องคุณไม่สามารถมีตัวปรับแต่งการเข้าถึงที่แตกต่างกันบนgetและsetก่อนหน้า C # 2.0 นอกจากนี้ฉันคิดว่าคุณกำลังผสม 2.0 และ 3.0 เนื่องจากชวเลขที่ติดตั้งอัตโนมัติที่คุณอ้างถึงคือ 3.0
Anthony Pegram

1

ฉันไม่เข้าใจความจำเป็นของการมีตัวตั้งค่าส่วนตัวซึ่งเริ่มต้นด้วย C # 2

ใช้กรณีตัวอย่าง:

ฉันมีตัวอย่างของแอปพลิเคชันอ็อบเจ็กต์'UserInfo'ที่มีคุณสมบัติSessionTokenIDV1ที่ฉันไม่ต้องการเปิดเผยต่อผู้บริโภคในคลาสของฉัน

ฉันยังต้องการความสามารถในการตั้งค่านั้นจากชั้นเรียนของฉัน

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

public class UserInfo
{
   public String SessionTokenIDV1 { get; set; }

}


public class Example
{
  // Private vars
  private UserInfo _userInfo = new UserInfo();

  public string SessionValidV1
  {
    get { return ((_userInfo.SessionTokenIDV1 != null) && (_userInfo.SessionTokenIDV1.Length > 0)) ? "set" : "unset"; }
    private set { _userInfo.SessionTokenIDV1 = value; }
  }
}

แก้ไข: แก้ไขแท็กรหัสแก้ไข: ตัวอย่างมีข้อผิดพลาดที่ได้รับการแก้ไข


-1

เครดิตhttps://www.dotnetperls.com/property

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

public class MyClass
{
    public MyClass()
    {
        // Set the private property.
        this.Name = "Sample Name from Inside";
    }
     public MyClass(string name)
    {
        // Set the private property.
        this.Name = name;
    }
    string _name;
    public string Name
    {
        get
        {
            return this._name;
        }
        private set
        {
            // Can only be called in this class.
            this._name = value;
        }
    }
}

class Program
{
    static void Main()
    {
        MyClass mc = new MyClass();
        Console.WriteLine(mc.name);

        MyClass mc2 = new MyClass("Sample Name from Outside");
        Console.WriteLine(mc2.name);
    }
}

โปรดดูภาพหน้าจอด้านล่างเมื่อฉันพยายามตั้งค่าจากนอกชั้นเรียน

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

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