อะไรคือความแตกต่างระหว่าง "instantiated" และ "initialized"?


105

ฉันเคยได้ยินสองคำนี้ที่ใช้ในบทช่วยสอนของ Microsoft สำหรับ VB.NET อะไรคือความแตกต่างระหว่างสองคำนี้เมื่อใช้ในการอ้างอิงถึงตัวแปร?

คำตอบ:


142

ประเภทการอ้างอิงที่มีต่อค่า

ตัวแปรใน C # อยู่ใน 1 จาก 2 กลุ่ม ประเภทค่าหรือประเภทการอ้างอิง ประเภทที่เหมือนintและDateTimeเป็นประเภทค่า ในทางตรงกันข้ามคลาสใด ๆ ที่คุณสร้างเป็นประเภทการอ้างอิง สตริง C # ยังเป็นประเภทอ้างอิง สิ่งต่างๆส่วนใหญ่ใน. NET framework เป็นประเภทอ้างอิง

ส่วนต่างๆของตัวแปร

มีตัวแปรเป็นชื่อและมันก็คุ้มค่า สองส่วน

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

ตัวแปรถูกกำหนดค่าเริ่มต้น

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

สำหรับประเภทค่าเช่นintคอมไพลเลอร์จะให้ค่าที่ถูกต้องหากคุณไม่ทำอย่างชัดเจน int's เริ่มต้นที่จะเป็นศูนย์โดยค่าเริ่มต้นDateTimeของการเริ่มต้นที่จะDateTime.MinValueเป็นค่าเริ่มต้น

ตัวแปรชนิดการอ้างอิงเริ่มต้นให้กับวัตถุที่คุณให้ไว้ คอมไพเลอร์จะไม่กำหนดอ็อบเจกต์ (เช่นค่าที่ถูกต้อง) ถ้าคุณไม่ทำ ในกรณีนี้ค่าคือnull- ไม่มีอะไร ดังนั้นเราจึงบอกว่าการอ้างอิงเริ่มต้นเป็นโมฆะ

อ็อบเจ็กต์ถูกสร้างอินสแตนซ์

มนุษย์เกิดมา วัตถุถูกสร้างอินสแตนซ์ ทารกเป็นตัวอย่างของมนุษย์วัตถุเป็นตัวอย่างของคลาสบางประเภท

การสร้างอินสแตนซ์ของคลาสเรียกว่าการสร้างอินสแตนซ์ (Ta-Da!)

ดังนั้นประกาศ , การเริ่มต้นและinstantiateมาร่วมกันเช่นนี้

MyClass myClassyReference = new MyClass();

ในข้างต้นไม่ถูกต้องที่จะกล่าวว่า "... การสร้างตัวอย่างของวัตถุ ... "


แก้ไข - แรงบันดาลใจจากการอภิปรายความคิดเห็น

มีสามสิ่งที่แตกต่างกัน (ด้านบน) โดยใช้คำศัพท์เฉพาะและคำศัพท์นั้นไม่สามารถใช้แทนกันได้:

  1. มีการประกาศตัวแปรอ้างอิง - MyClass myClassyReference
  2. วัตถุถูกสร้างอินสแตนซ์ (... จาก / ของคลาสที่กำหนดโดยนัย) -new MyClass()
  3. วัตถุถูกกำหนดให้กับตัวแปร =.

การสรุปข้อเท็จจริง:

  1. ตัวแปรประเภทการอ้างอิงเรียกอีกอย่างว่า "การอ้างอิง" "ตัวแปรประเภทค่า" ไม่ใช่ข้อมูลอ้างอิง

  2. สิ่งนี้: "objectA เป็นตัวอย่างของวัตถุ" เป็นสิ่งที่ไม่ถูกต้องอย่างยิ่ง ถ้า objectA เป็น "อินสแตนซ์ของ objectB" ก็ต้องเป็น object นั้น A เริ่มต้นชีวิตด้วย type ของ objectB ไม่ว่าจะเป็นอะไรก็ตาม - และสถานะปัจจุบันไม่ว่าจะเป็นอะไรก็ตาม สิ่งที่เกี่ยวกับการสร้างวัตถุ D, E และ F เมื่อ objectB เปลี่ยนแปลง? เปล่าเนอะ! เป็นกรณีเชิงแนวคิดและทางเทคนิค "objectA เป็นตัวอย่างของคลาส" "การสร้างอินสแตนซ์" และ "อินสแตนซ์ของ" มีความหมายที่ชัดเจน - วัตถุได้รับประเภทคำจำกัดความและค่าจากคลาส

  3. MyClass myClassyReference = null โดยทั่วไปเราไม่พูดว่า "ตัวแปรถูกกำหนดให้เป็นโมฆะ" และเราไม่เคยพูดว่า "ตัวแปรอ้างอิง null" ไม่ใช่ แต่เราพูดว่า "ตัวแปรเป็นโมฆะ"; หรือ "ตัวแปรไม่ได้อ้างอิงอะไรเลย" หรือ "การอ้างอิงเป็นโมฆะ"

การใช้งานจริง:

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

  • ฉันเห็นสิ่งนี้ในรหัสของคุณ

    MyClass myClassyReference;
    myClassyReference.DoSomething();

    "คุณประกาศตัวแปร แต่ไม่เคยกำหนดมันเป็นโมฆะดังนั้นจึงไม่ได้อ้างอิงอะไรเลยนั่นเป็นสาเหตุที่การเรียกใช้เมธอดทำให้เกิดข้อยกเว้น"

สิ้นสุดการแก้ไข


ความสว่างที่เหลือทนของการเป็นอยู่

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

instantiatedวัตถุหรืออาจจะไม่ได้มีการอ้างอิงถึงมัน

instantiatedวัตถุอาจจะมีหลายที่อ้างอิงกับมัน

การอ้างอิงที่ประกาศอาจชี้ไปที่วัตถุหรือไม่ก็ได้


คำอธิบายที่สมบูรณ์แบบ!
M. Fawad Surosh

ถ้าจะพูดผิด: "... การสร้างตัวอย่างของวัตถุ ... " คุณควรพูดอย่างไร? "... สร้างอินสแตนซ์วัตถุและกำหนดการอ้างอิงให้กับมัน ... "?
Aaron Dake

หรือสิ่งที่เกี่ยวกับ: "... สร้างอินสแตนซ์อ็อบเจ็กต์และเริ่มต้นตัวแปรเพื่ออ้างอิงถึง"? ซึ่งรวมถึงทั้งคำและดูเหมือนจะสะกดทุกคำ - แม้ว่าจะค่อนข้างยาว คุณคิดอย่างไร?
Aaron Dake

... จะว่ายังไงดี? พูดว่า: "กำลังสร้างอินสแตนซ์ของคลาส" ไม่ใช่ "... ของวัตถุ" และ "การสร้างอินสแตนซ์ของตัวแปรไปยังการอ้างอิงของมัน" เป็นการพูดคุยสองครั้งและผิด 2 วิธี: (1) มีเพียง Objects เท่านั้นที่สร้างอินสแตนซ์ (2) ตัวแปร 'ชี้ไปที่' วัตถุคือตัวแปรอ้างอิงหรือเรียกสั้น ๆ ว่าตัวแปรคือการอ้างอิง ฉันจะบอกว่ามันแตกต่างกัน: ตัวแปร "ประเภทอ้างอิง" คือข้อมูลอ้างอิง หมายถึง - หรือชี้ไปที่ - วัตถุ
radarbob

40

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

ตัวอย่างเช่นนี่คือตัวแปร:

Dim obj as Object

ตัวแปรนี้ยังไม่ได้รับการเริ่มต้น เมื่อฉันกำหนดค่าให้กับobjตัวแปรตัวแปรจะเริ่มต้น นี่คือตัวอย่างของการเริ่มต้น:

obj = 1
obj = "foo"

การสร้างอินสแตนซ์เป็นสิ่งที่แตกต่างกันมาก แต่เกี่ยวข้องกันเนื่องจากการสร้างอินสแตนซ์มักจะตามด้วยการเริ่มต้น:

Dim obj As New Object()

ในบรรทัดก่อน ๆ ของรหัสที่objตัวแปรเริ่มต้นได้มีการอ้างอิงไปยังใหม่Objectที่อินสแตนซ์ เราบอกว่าสิ่งใหม่Objectถูกสร้างอินสแตนซ์เนื่องจากเราได้สร้างอินสแตนซ์ใหม่ขึ้นมา

ตอนนี้ฉันเชื่อว่า VB.NET ทำให้เกิดความสับสนมากกว่า C # เพราะไม่ชัดเจนว่ามีการมอบหมายงานในโค้ดด้านบน ใน C # จะชัดเจนกว่ามากว่ามีทั้งการสร้างอินสแตนซ์ของอินสแตนซ์และการเริ่มต้นของตัวแปร:

Object obj = new Object();

@ วัตถุแอนดรู obj = 1; คือการเริ่มต้นและวัตถุ obj = วัตถุใหม่ () / คือการสร้างอินสแตนซ์และการเริ่มต้นนี่คือสิ่งที่คุณได้กล่าวถึง ตอนนี้ฉันอยากถามคุณสองเรื่อง 1. นี่คืออะไร? วัตถุ obj; เหรอ? 2. มีการจัดสรรหน่วยความจำเมื่อฉันใช้ object obj หรือไม่ ?? หรือมีการจัดตำแหน่งเมื่อฉันเริ่มต้นโดยวัตถุรหัสนี้ obj = 1; เหรอ?
kashif

ฉันจะบอกว่า "object obj" คือการประกาศและไม่ยังไม่มีการจัดสรรหน่วยความจำ หรืออย่างน้อยก็มีเพียงหน่วยความจำเพียงพอที่จะเก็บค่า "null" หน่วยความจำจริงสำหรับตัวแปรจะถูกจัดสรรตามค่าเมื่อเริ่มต้นแล้ว
Aaron Dake

14

ในการเริ่มต้นบางสิ่งบางอย่างคือการตั้งค่าเป็นค่าเริ่มต้น ในการสร้างอินสแตนซ์บางสิ่งคือการสร้างอินสแตนซ์ของมัน

บ่อยครั้งนี่คือสิ่งเดียวกันไม่มากก็น้อย นี้:

SqlConnection conn = new SqlConnection();

instantiatesSqlConnectionวัตถุและเริ่มต้นconnตัวแปรโดยการตั้งค่าไปยังอินสแตนซ์ที่

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


4

* การสร้างอินสแตนซ์หมายถึงการสร้างอินสแตนซ์สำหรับคลาสหรืออ็อบเจ็กต์การเริ่มต้นหมายถึงการ * เริ่มต้นอ็อบเจ็กต์หรือคลาสเดียวกันเพื่อวัตถุประสงค์ใด ๆ **


3

สร้างอินสแตนซ์หมายความว่ามีการสร้างอินสแตนซ์ของวัตถุ เริ่มต้นหมายความว่าวัตถุเดียวกันนั้นได้ทำการเริ่มต้นบางอย่างแล้ว


2

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


2

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

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

วัตถุอาจเริ่มต้นสิ่งอื่น ๆ บางอย่างหรือแม้แต่สร้างอินสแตนซ์อ็อบเจ็กต์อื่นเป็นส่วนหนึ่งของการเริ่มต้น

ความแตกต่างคือการสร้างอินสแตนซ์เป็นการสร้างสิ่งที่สามารถทำสิ่งต่างๆได้ การเริ่มต้นคือสิ่งที่ต้องทำ



1

เราสามารถเห็นได้ด้วยวิธีนี้ สำหรับบรรทัดรหัสด้านล่าง:

var p = new Person();

บรรทัดด้านบนสามารถอ่านได้สองวิธีดังต่อไปนี้:

  1. ตัวแปร p ถูกเตรียมใช้งานเป็นคลาสบุคคล
  2. คลาสบุคคลถูกสร้างอินสแตนซ์ในตัวแปร p

เรื่องของการอ้างอิงหรือบริบทมีความสำคัญ เมื่อพูดถึงในแง่ของตัวแปรเราจะใช้คำว่าการเริ่มต้น เมื่อพูดถึงในแง่ของระดับ / ประเภทที่เราใช้คำว่าinstantiate


0

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

เช่น: SqlConnection conn = new SqlConnection();

นี่newคือคีย์เวิร์ดที่จัดสรรหน่วยความจำสำหรับอินสแตนซ์และconnเป็นชื่อตัวแปรที่กำหนดสำหรับอินสแตนซ์นั้น


0

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

class P { string name = "Ralf"; }

WriteLine(new P().name); // "Ralf";
WriteLine((FormatterServices.GetUninitializedObject(typeof(P)) as P).name); // null

GetUninitializedObject ไม่เรียกตัวสร้างเพื่อสร้างอินสแตนซ์วัตถุที่นั่น (แต่เวทมนตร์ภายในบางอย่าง)

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

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