ค่าเริ่มต้น (วัตถุ) คืออะไร ทำใน C #?


136

Googling เป็นเพียงคีย์เวิร์ด แต่ฉันพบโค้ดบางตัวที่ระบุว่า

MyVariable = default(MyObject);

และฉันสงสัยว่ามันหมายถึงอะไร

คำตอบ:


190
  • สำหรับชนิดการอ้างอิงจะส่งกลับ null
  • สำหรับชนิดค่าอื่นที่ไม่ใช่Nullable<T>จะส่งกลับค่าเริ่มต้นเป็นศูนย์
  • เนื่องจากNullable<T>จะส่งคืนค่าว่าง (pseudo-null) (อันที่จริงนี่เป็นคำสั่งซ้ำของสัญลักษณ์แสดงหัวข้อย่อยแรก แต่ควรทำให้ชัดเจน)

การใช้งานที่ใหญ่ที่สุดdefault(T)คือในยาชื่อสามัญและสิ่งต่างๆเช่นTry...รูปแบบ:

bool TryGetValue(out T value) {
    if(NoDataIsAvailable) {
        value = default(T); // because I have to set it to *something*
        return false;
    }
    value = GetData();
    return true;
}

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

bool someField = default(bool);
int someOtherField = default(int)
global::My.Namespace.SomeType another = default(global::My.Namespace.SomeType);

1
ถ้าฉันสร้างclass Fooด้วยทรัพย์สินint n. ฉันสามารถ "เกิน" defaultเพื่อให้ตั้งค่าnเป็นพูด5แทนได้0หรือไม่
Pratik Deoghare

4
@ The Machine Charmer: ไม่คุณไม่สามารถโอเวอร์โหลดdefaultได้
Jeff Yates

ไม่int foo = default(int);เหมือนเดิมint foo;? เช่นไม่ได้กำหนดค่าเริ่มต้น ints เริ่มต้นให้มีค่าเดียวกับdefault(int)?
Adam Parkin

1
@AdamParkin ที่ขึ้นอยู่กับว่าคุณกำลังพูดถึงเขตข้อมูลกับชาวบ้าน ใช่ฟิลด์เริ่มต้นเป็นช่องว่างศูนย์เช่นเดียวกับdefault(...); ชาวบ้านไม่มีค่าเริ่มต้น (แม้ว่าในทางเทคนิค.locals initใน IL หมายความว่าค่าเริ่มต้นจะเป็นศูนย์อีกครั้ง แต่คุณต้องใช้กลไกที่ไม่ปลอดภัยในการสังเกต)
Marc Gravell

"มันส่งคืนค่าว่าง (psuedo-null) ที่ ... นั่นอะไรดูเหมือนว่าประโยคจะไม่เสร็จสิ้น

16

defaultคำหลักจะส่งกลับnullสำหรับประเภทการอ้างอิงและzeroสำหรับประเภทค่าตัวเลข

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

จาก MSDN

Simple Sample code :<br>
    class Foo
    {
        public string Bar { get; set; }
    }

    struct Bar
    {
        public int FooBar { get; set; }
        public Foo BarFoo { get; set; }
    }

    public class AddPrinterConnection
    {
        public static void Main()
        {

            int n = default(int);
            Foo f = default(Foo);
            Bar b = default(Bar);

            Console.WriteLine(n);

            if (f == null) Console.WriteLine("f is null");

            Console.WriteLine("b.FooBar = {0}",b.FooBar);

            if (b.BarFoo == null) Console.WriteLine("b.BarFoo is null");

        }
    }

เอาท์พุท:

0
f is null
b.FooBar = 0
b.BarFoo is null

3

ค่าเริ่มต้นของMyObject. ดูคำหลักเริ่มต้นในรหัสทั่วไป (คู่มือการเขียนโปรแกรม C #) (MSDN):

ในคลาสและวิธีการทั่วไปปัญหาหนึ่งที่เกิดขึ้นคือการกำหนดค่าเริ่มต้นให้กับประเภท T ที่กำหนดพารามิเตอร์เมื่อคุณไม่ทราบสิ่งต่อไปนี้ล่วงหน้า:

  • ไม่ว่า T จะเป็นประเภทอ้างอิงหรือประเภทค่า
  • ถ้า T เป็นประเภทค่าไม่ว่าจะเป็นค่าตัวเลขหรือโครงสร้าง

กำหนดตัวแปร t ของชนิดที่กำหนดพารามิเตอร์ T คำสั่ง t = null จะใช้ได้ก็ต่อเมื่อ T เป็นประเภทอ้างอิงและ t = 0 จะใช้ได้เฉพาะกับประเภทค่าตัวเลขเท่านั้น แต่ไม่สามารถใช้กับโครงสร้างได้ วิธีแก้ปัญหาคือการใช้คีย์เวิร์ดเริ่มต้นซึ่งจะคืนค่า null สำหรับประเภทการอ้างอิงและศูนย์สำหรับประเภทค่าตัวเลข สำหรับโครงสร้างจะส่งคืนสมาชิกแต่ละคนของโครงสร้างที่เริ่มต้นเป็นศูนย์หรือว่างขึ้นอยู่กับว่าเป็นค่าหรือชนิดการอ้างอิง ตัวอย่างต่อไปนี้จากคลาส GenericList แสดงวิธีใช้คีย์เวิร์ดเริ่มต้น สำหรับข้อมูลเพิ่มเติมโปรดดูภาพรวม Generics

public class GenericList<T>
{
    private class Node
    {
        //...

        public Node Next;
        public T Data;
    }

    private Node head;

    //...

    public T GetNext()
    {
        T temp = default(T);

        Node current = head;
        if (current != null)
        {
            temp = current.Data;
            current = current.Next;
        }
        return temp;
    }
}


1

defaultผลตอบแทนที่คำว่า "เริ่มต้น" หรือ "ว่างเปล่า" ความคุ้มค่าตัวแปรของชนิดที่มีการร้องขอ

เหมาะสำหรับทุกสภาพการอ้างอิง (กำหนดด้วยclass, delegateฯลฯ ) nullนี้เป็น สำหรับประเภทค่า (กำหนดด้วยstruct, enumฯลฯ ) มันเป็นมูลค่าทั้งหมด zeroes (ตัวอย่างเช่นint 0, DateTime 0001-01-01 00:00:00ฯลฯ )

ส่วนใหญ่จะใช้กับรหัสทั่วไปที่ใช้ได้กับทั้งการอ้างอิงและประเภทค่าเนื่องจากคุณไม่สามารถกำหนดnullให้กับตัวแปรประเภทค่าได้


0

มันจะตั้งค่าเริ่มต้นของออบเจ็กต์เป็นตัวแปร: null สำหรับชนิดอ้างอิงและ 0 สำหรับชนิดค่า


0

บางทีนี่อาจช่วยคุณได้:

using System;
using System.Collections.Generic;
namespace Wrox.ProCSharp.Generics
{
    public class DocumentManager < T >
    {
        private readonly Queue < T > documentQueue = new Queue < T > ();
        public void AddDocument(T doc)
        {
            lock (this)
            {
                documentQueue.Enqueue(doc);
            }
        }

        public bool IsDocumentAvailable
        {
            get { return documentQueue.Count > 0; }
        }
    }
}

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

public T GetDocument()
{
    T doc = default(T);
    lock (this)
    {
        doc = documentQueue.Dequeue();
    }
    return doc;
}

คำหลักเริ่มต้นมีหลายความหมายขึ้นอยู่กับบริบทที่ใช้ คำสั่ง switch ใช้ค่าดีฟอลต์สำหรับการกำหนดเคสดีฟอลต์และด้วย generics ค่าดีฟอลต์จะใช้เพื่อเริ่มต้นชนิดทั่วไปเป็น null หรือ 0 ขึ้นอยู่กับว่าเป็นการอ้างอิงหรือประเภทค่า


0

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

รหัสผิด

public void TestChanges<T>(T inputValue)

            try
            {
                if (inputValue==null)
                    return;
                //operation on inputValue

           }
            catch
            {
                // ignore this.
            }
        }

แก้ไข

public void TestChanges<T>(T inputValue)

            try
            {
                if (object.Equals(inputValue, default(T)) )
                    return;
                //operation on inputValue

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