มันสมเหตุสมผลไหมที่จะใช้“ เป็น” แทนที่จะใช้ตัวละครถึงแม้ว่าจะไม่มีการตรวจสอบที่เป็นโมฆะ? [ปิด]


351

ในบล็อกการพัฒนาตัวอย่างรหัสออนไลน์และ (เมื่อเร็ว ๆ นี้) แม้แต่หนังสือฉันยังคงสะดุดเกี่ยวกับรหัสเช่นนี้:

var y = x as T;
y.SomeMethod();

หรือแย่ยิ่งกว่า:

(x as T).SomeMethod();

นั่นไม่สมเหตุสมผลสำหรับฉัน ถ้าคุณแน่ใจว่าxเป็นประเภทที่คุณควรใช้โยนโดยตรง:T (T)xหากคุณไม่แน่ใจคุณสามารถใช้asแต่จำเป็นต้องตรวจสอบnullก่อนดำเนินการบางอย่าง ทุกสิ่งที่โค้ดข้างต้นไม่สามารถที่จะเปิด (ประโยชน์) InvalidCastExceptionเป็น NullReferenceException(ไม่มีประโยชน์)

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


56
จะสนุกกว่าที่จะเห็น (จูบในฐานะ S). SteveIsSuchA (); แต่ฉันเห็นด้วยมันเป็นการละเมิด
SwDevMan81

5
มันเจ๋งกว่าการเขียน((T)x).SomeMethod()ใช่ไหม? ;) (แค่ล้อเล่นคุณพูดถูก!)
Lucero

8
@P Daddy ฉันไม่เห็นด้วยคำถามที่ดีอย่างสมบูรณ์ (ทำรูปแบบรหัสนี้ทำให้รู้สึกจริง) และมีประโยชน์มาก +1 กับคำถามและขมวดคิ้วกับทุกคนที่ลงคะแนนให้ปิด
MarkJ

9
Lucerno ถูกต้องรูปแบบการเข้ารหัสนี้เกิดจากการพยายามหลีกเลี่ยงวงเล็บ รักษาไม่หายหลังจากได้รับเสียงกระเพื่อม
ฮันส์ Passant

13
รหัสที่ปรับให้เหมาะสม: (f as T).SomeMethod();)
MSalters

คำตอบ:


252

ความเข้าใจของคุณเป็นเรื่องจริง ฟังดูเหมือนจะพยายามเพิ่มประสิทธิภาพให้ฉัน คุณควรใช้นักแสดงปกติเมื่อคุณแน่ใจในประเภท นอกเหนือจากการสร้างข้อยกเว้นที่สมเหตุสมผลมากขึ้นแล้วมันยังล้มเหลวอย่างรวดเร็ว หากคุณคิดผิดเกี่ยวกับประเภทของโปรแกรมของคุณจะล้มเหลวทันทีและคุณจะสามารถเห็นสาเหตุของความล้มเหลวได้ทันทีแทนที่จะรอสักครู่NullReferenceExceptionหรือArgumentNullExceptionมีข้อผิดพลาดเชิงตรรกะในอนาคต โดยทั่วไปการasแสดงออกที่ไม่ได้ตามมาด้วยการnullตรวจสอบที่ไหนสักแห่งเป็นกลิ่นรหัส

ในทางกลับกันหากคุณไม่แน่ใจเกี่ยวกับนักแสดงและคาดว่าจะล้มเหลวคุณควรใช้asแทนที่จะใช้บล็อกธรรมดาที่มีtry-catchบล็อก นอกจากนี้asแนะนำให้ใช้มากกว่าการตรวจสอบประเภทตามด้วยนักแสดง แทน:

if (x is SomeType)
   ((SomeType)x).SomeMethod();

ซึ่งสร้างisinstคำแนะนำสำหรับisคำหลักและcastclassคำแนะนำสำหรับนักแสดง (ประสิทธิภาพในการส่งนักแสดงสองครั้ง) คุณควรใช้:

var v = x as SomeType;
if (v != null)
    v.SomeMethod();

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


ไม่แนะนำวิธีแก้ไขปัญหาต่อไปนี้เพื่อใช้ในรหัสการผลิต หากคุณเกลียดการสร้างพื้นฐานใน C # จริงๆคุณอาจลองเปลี่ยนมาใช้ VB หรือภาษาอื่น ๆ

ในกรณีที่ผู้หนึ่งเกลียดไวยากรณ์การร่ายเขาสามารถเขียนวิธีการขยายเพื่อเลียนแบบนักแสดง:

public static T To<T>(this object o) { // Name it as you like: As, Cast, To, ...
    return (T)o;
}

และใช้ไวยากรณ์ [?] ที่เรียบร้อย:

obj.To<SomeType>().SomeMethod()

5
ฉันคิดว่าสภาพการแข่งขันไม่เกี่ยวข้อง หากคุณประสบปัญหานี้แสดงว่ารหัสของคุณไม่ปลอดภัยสำหรับเธรดและมีวิธีการแก้ปัญหาที่เชื่อถือได้มากกว่าการใช้คำหลัก "เป็น" +1 สำหรับคำตอบที่เหลือ
RMorrisey

10
@RMorrisey: ฉันมีตัวอย่างอย่างน้อยหนึ่งในใจ: สมมติคุณมีวัตถุที่หัวข้ออื่นพยายามที่จะทำให้การได้โดยการตั้งค่าให้cache nullในสถานการณ์ที่ไม่มีล็อคสิ่งต่าง ๆ เหล่านี้สามารถเกิดขึ้นได้
Mehrdad Afshari

10
is + cast นั้นเพียงพอที่จะทริกเกอร์คำเตือน "อย่าส่งโดยไม่จำเป็น" จาก FxCop: msdn.microsoft.com/en-us/library/ms182271.aspxนั่นควรจะเป็นเหตุผลเพียงพอที่จะหลีกเลี่ยงการสร้าง
David Schmitt

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

2
@MgSam เห็นได้ชัดว่ากรณีการใช้งานดังกล่าวไม่เหมาะสมสำหรับToวิธีการที่นี่เนื่องจากแปลงเฉพาะลำดับชั้นการสืบทอดซึ่งสำหรับประเภทค่าจะเกี่ยวข้องกับการต่อสู้ แน่นอนว่าความคิดทั้งหมดเป็นไปในทางทฤษฎีมากกว่าจริงจัง
Mehrdad Afshari


40

การใช้ 'as' ไม่ได้ใช้การแปลงที่ผู้ใช้กำหนดในขณะที่นักแสดงจะใช้พวกเขาตามความเหมาะสม นั่นอาจเป็นความแตกต่างที่สำคัญในบางกรณี


5
นี่เป็นสิ่งสำคัญที่ต้องจำ Eric Lippert อ่านมากกว่านี้ที่นี่: blogs.msdn.com/ericlippert/archive/2009/10/08/…
P Daddy

5
ความคิดเห็นดี, P! หากรหัสของคุณขึ้นอยู่กับความแตกต่างนี้ฉันจะบอกว่ามีเซสชันการแก้ไขข้อบกพร่องในช่วงดึกของคุณในอนาคต
TrueWill

36

ฉันเขียนเรื่องนี้เล็กน้อยที่นี่:

http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx

ฉันเข้าใจประเด็นของคุณ และฉันเห็นด้วยกับแรงผลักดันของมัน: ผู้ดำเนินการนักสื่อสารสื่อสาร "ฉันแน่ใจว่าวัตถุนี้สามารถแปลงเป็นประเภทนั้นและฉันยินดีที่จะเสี่ยงยกเว้นถ้าฉันผิด" ในขณะที่ "เป็น" ผู้ประกอบการสื่อสาร "ฉันไม่แน่ใจว่าวัตถุนี้สามารถแปลงเป็นประเภทนั้นให้ฉันเป็นโมฆะถ้าฉันผิด"

อย่างไรก็ตามมีความแตกต่างเล็กน้อย (x เป็น T). สิ่งใด () สื่อสาร "ฉันรู้ไม่เพียงว่า x สามารถแปลงเป็น T ได้ แต่ยิ่งไปกว่านั้นการทำเช่นนั้นเกี่ยวข้องกับการอ้างอิงหรือการแปลง unboxing เท่านั้นและยิ่งไปกว่านั้น x ไม่ใช่โมฆะ" นั่นเป็นการสื่อสารข้อมูลที่แตกต่างจาก (T) x) .Wh สิ่งที่ () และบางทีนั่นอาจเป็นสิ่งที่ผู้เขียนรหัสตั้งใจ


1
ฉันไม่เห็นด้วยกับการป้องกันการเก็งกำไรของคุณของผู้เขียนรหัสในประโยคสุดท้ายของคุณ ((T)x).Whatever() ยังสื่อสารที่xไม่ได้ [ตั้งใจจะให้] โมฆะและผมมีข้อสงสัยอย่างมากที่ผู้เขียนมักจะต้องมีการดูแลไม่ว่าจะเป็นแปลงที่จะTเกิดขึ้นมีการอ้างอิงหรือแกะกล่องแปลงเท่านั้นหรือถ้ามันจำเป็นต้องมีผู้ใช้กำหนดหรือการเป็นตัวแทนการเปลี่ยนแปลงการแปลง ท้ายที่สุดถ้าฉันนิยามpublic static explicit operator Foo(Bar b){}มันก็เป็นความตั้งใจของฉันที่ชัดเจนว่าBarเข้ากันได้กับ Fooเป็นเรื่องยากที่ฉันจะหลีกเลี่ยงการแปลงนี้
Paddy พ่อ

4
บางทีผู้เขียนโค้ดส่วนใหญ่คงไม่แยกความแตกต่างนั้น ฉันอาจจะเป็นส่วนตัว แต่ถ้าเป็นฉันจะเพิ่มความคิดเห็นลงในเอฟเฟกต์นั้น
Eric Lippert

16

ฉันมักจะเห็นการอ้างอิงถึงบทความที่ทำให้เข้าใจผิดนี้เป็นหลักฐานว่า "เป็น" เร็วกว่าการคัดเลือก

อีกด้านหนึ่งที่ทำให้เข้าใจผิดที่ชัดเจนมากขึ้นของบทความนี้คือกราฟิกซึ่งไม่ได้ระบุสิ่งที่กำลังถูกวัด: ฉันสงสัยว่ามันเป็นการวัดที่ไม่ได้ปลดเปลื้อง (โดยที่ "เป็น" เห็นได้ชัดว่าเร็วกว่ามาก

หากคุณใช้เวลาในการทำการวัดคุณจะเห็นว่าการคัดเลือกนักแสดงนั้นเร็วกว่า "เป็น" เมื่อนักแสดงประสบความสำเร็จ

ฉันสงสัยว่านี่อาจเป็นเหตุผลหนึ่งในการใช้คำว่า "ขนส่งสินค้าลัทธิ" ของคำหลักแทนการส่ง


2
ขอบคุณสำหรับลิงค์ที่น่าสนใจมาก จากวิธีการที่ฉันเข้าใจบทความที่เขาไม่เปรียบเทียบกรณีที่ไม่ใช่ข้อยกเว้น อย่างไรก็ตามบทความนี้เขียนขึ้นสำหรับ. net 1.1 และความคิดเห็นชี้ให้เห็นว่าสิ่งนี้เปลี่ยนไปใน. net 2.0: ประสิทธิภาพตอนนี้เกือบเท่ากันแล้ว
Heinzi

1
บทความนี้แปลว่าเขากำลังเปรียบเทียบกรณีที่ไม่ใช่ข้อยกเว้น แต่ฉันทำการทดสอบบางอย่างมานานแล้วและไม่สามารถทำซ้ำผลลัพธ์ที่อ้างสิทธิ์ของเขาได้แม้ว่าจะใช้กับ. NET 1.x และเนื่องจากบทความไม่ได้ให้รหัสที่ใช้ในการรันเกณฑ์มาตรฐานจึงเป็นไปไม่ได้ที่จะบอกว่าสิ่งใดที่ถูกเปรียบเทียบ
Joe

"ลัทธิลัทธิขนส่งสินค้า" - สมบูรณ์แบบ ตรวจสอบ "Cargo Cult Science Richard Feynman" สำหรับข้อมูลทั้งหมด
Bob Denny

11

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

ตกลงในสิ่งยกเว้นแม้ว่า แต่อย่างน้อยสำหรับฉันการใช้งานส่วนใหญ่ของasต้มลงไปตรวจสอบในnullภายหลังซึ่งฉันพบว่าดีกว่าจับข้อยกเว้น


8

99% ของเวลาที่ฉันใช้ "as" คือเมื่อฉันไม่แน่ใจว่าเป็นประเภทวัตถุจริง

var x = obj as T;
if(x != null){
 //x was type T!
}

และฉันไม่ต้องการที่จะจับข้อยกเว้นการโยนที่ชัดเจนและทำให้การโยนสองครั้งโดยใช้ "คือ":

//I don't like this
if(obj is T){
  var x = (T)obj; 
}

8
asคุณได้อธิบายเพียงกรณีการใช้งานที่เหมาะสมสำหรับ อะไรอีก 1%
Paddy พ่อ

ในการพิมพ์ผิด? =) ฉันหมายถึง 99% ของเวลาที่ฉันใช้ข้อมูลโค้ดที่แน่นอนนี้บางครั้งฉันอาจใช้ "เป็น" ในการเรียกใช้เมธอดหรือที่อื่น
Max Galkin

D'oh และมันมีประโยชน์น้อยกว่าคำตอบที่ได้รับความนิยมอันดับสองใช่หรือไม่?
Max Galkin

2
+1 ฉันเห็นด้วยกับการเรียกสิ่งนี้ว่ามีค่าเท่ากับคำตอบของ Rubens Farias - ผู้คนจะมาที่นี่อย่างหวังและนี่จะเป็นตัวอย่างที่มีประโยชน์
Ruben Bartelink

8

มันเป็นเพราะคนชอบวิธีที่มันดูมันอ่านง่ายมาก

ให้เผชิญหน้ากับมัน: ตัวดำเนินการหล่อ / การแปลงในภาษา C เหมือนจะแย่มากอ่านง่าย ฉันอยากให้ดีขึ้นถ้า C # ใช้ไวยากรณ์ Javascript ของ:

object o = 1;
int i = int(o);

หรือกำหนดtoผู้ประกอบการเทียบเท่าการหล่อของas:

object o = 1;
int i = o to int;

เพื่อให้คุณรู้ว่าอนุญาตให้ใช้ไวยากรณ์ JavaScript ที่คุณกล่าวถึงใน C ++
Paddy พ่อ

@PDaddy: มันไม่ตรง 100% เข้ากันได้ไวยากรณ์สำรองและแม้ว่าจะไม่ได้ตั้งใจจะให้เป็นที่ (ประกอบ X VS คอนสตรัคแปลง)
Ruben Bartelink

ฉันต้องการให้ใช้ไวยากรณ์ C ++ ของdynamic_cast<>()(และคล้ายกัน) คุณกำลังทำสิ่งที่น่าเกลียดมันควรจะดูน่าเกลียด
Tom Hawtin - tackline

5

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

ย้อนกลับไปที่หัวข้อ ... เมื่อใช้การส่งโดยตรงมีความเป็นไปได้สำหรับการยกเว้นการส่งที่ไม่ถูกต้อง ดังนั้นผู้คนจึงนำไปใช้asเป็นโซลูชั่นครอบคลุมความต้องการการหล่อของพวกเขาเพราะas(โดยตัวเอง) จะไม่มีข้อยกเว้น แต่สิ่งที่ตลกเกี่ยวกับสิ่งนั้นคือในตัวอย่างที่คุณให้(x as T).SomeMethod();คุณซื้อขายข้อยกเว้นการส่งแบบไม่ถูกต้องสำหรับข้อยกเว้นการอ้างอิงแบบ null ซึ่งทำให้งงงวยปัญหาที่แท้จริงเมื่อคุณเห็นข้อยกเว้น

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


2
"ฉันชอบ is is test" - "is" ตามมาด้วย cast แน่นอนว่าช้ากว่า "as" ตามด้วย test สำหรับ null (เช่นเดียวกับ "IDictionary.ContainsKey" ตามด้วย dereferencing โดยใช้ indexer นั้นช้ากว่า "IDictionary.TryGetValue ") แต่ถ้าคุณพบว่าอ่านง่ายขึ้นไม่ต้องสงสัยเลยว่าความแตกต่างนั้นไม่ค่อยสำคัญ
โจ

คำแถลงที่สำคัญในตอนกลางคือวิธีการที่คนใช้asเป็นวิธีแก้ปัญหาแบบครอบคลุมเพราะทำให้พวกเขารู้สึกปลอดภัย
Bob

5

นี้จะต้องมีหนึ่งของฉันpeeves ด้านบน

Stroustrup ของ D & E และ / หรือบางบล็อกโพสต์ฉันลาดเทพบในขณะนี้กล่าวถึงความคิดของการเป็นtoผู้ประกอบการซึ่งจะอยู่ที่จุดที่ทำโดยhttps://stackoverflow.com/users/73070/johannes-rossel (เช่นเดียวกับไวยากรณ์asแต่มีDirectCastความหมาย )

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

น่าเสียดายที่โปรแกรมเมอร์ 'ฉลาด' (มักจะเป็นนักเขียนหนังสือ (Juval Lowy IIRC)) ทำสิ่งนี้โดยการใช้asวิธีนี้ (C ++ ไม่มีข้อเสนอasอาจเป็นเพราะเหตุผลนี้)

แม้ VB มีความสอดคล้องมากขึ้นในการมีไวยากรณ์เครื่องแบบที่บังคับให้คุณเลือกTryCastหรือDirectCastและให้ขึ้นใจของคุณ !


+1 คุณอาจจะหมายถึงDirectCast พฤติกรรมที่ไม่ไวยากรณ์
Heinzi

@Heinzi: Ta สำหรับ +1 จุดดี. ตัดสินใจที่จะฉลาดและใช้semanticsแทน: P
Ruben Bartelink

เนื่องจาก C # ไม่มีข้ออ้างใด ๆ ที่เข้ากันได้กับ C, C ++ หรือ Java ฉันพบว่าตัวเองโกรธกับบางสิ่งที่ยืมมาจากภาษาเหล่านั้น มันเกินกว่า "ฉันรู้ว่านี่คือ X" และ "ฉันรู้ว่านี่ไม่ใช่ X แต่สามารถแสดงเป็นหนึ่งได้" ถึง "ฉันรู้ว่านี่ไม่ใช่ X และอาจไม่สามารถแทนได้อย่างใดอย่างหนึ่ง แต่ขอ X ให้ฉันด้วย " ฉันเห็นว่ามีประโยชน์สำหรับdouble-to-intนักแสดงที่จะล้มเหลวถ้าสิ่งdoubleนั้นไม่ได้แทนค่าที่แน่นอนที่สามารถใส่ได้Int32แต่การ(int)-1.5ให้ -1 ก็น่าเกลียด
supercat

@supercat Yep แต่การออกแบบภาษาไม่ง่ายเหมือนที่เราทุกคนรู้ - ดูชุดของการแลกเปลี่ยนที่เกี่ยวข้องใน C # nullables ยาแก้พิษที่รู้จักกันเพียงอย่างเดียวคือการอ่าน C # ในรุ่น Depth เมื่อพวกเขาเข้ามาเป็นประจำ :) โชคดีที่ฉันกังวลเกี่ยวกับการทำความเข้าใจความแตกต่างของ F # ในทุกวันนี้และมันมีสติมากขึ้นในเรื่องเหล่านี้
Ruben Bartelink

@RubenBartelink: ฉันยังไม่ชัดเจนว่าปัญหาที่แน่นอนประเภท nullable ควรจะแก้ไข แต่ฉันคิดว่าในกรณีส่วนใหญ่มันจะดีกว่าที่จะมีMaybeValid<T>เขตข้อมูลสาธารณะสองIsValidและValueรหัสที่สามารถทำได้ตามที่เห็นสมควร MaybeValid<TValue> TryGetValue(TKey key) { var ret = default(MaybeValid<TValue>); ret.IsValid = dict.TryGetValue(key, out ret.Value); return ret; }ที่จะต้องได้รับอนุญาตเช่น ไม่เพียง แต่จะช่วยประหยัดการคัดลอกอย่างน้อยสองรายการNullable<T>เท่านั้น แต่ยังคุ้มค่ากับประเภทอื่น ๆT - ไม่เพียงแค่คลาส
supercat

2

ฉันเชื่อว่าasคำหลักอาจถือเป็นรุ่นที่ดูหรูหรากว่า dynamic_castจาก C ++


ฉันจะบอกว่านักแสดงที่ตรงใน C # เป็นเหมือนdynamic_castC ++
Paddy พ่อ

ฉันคิดว่าการส่งแบบตรงใน C # นั้นเทียบเท่ากับ static_cast ใน C ++ มากกว่า
Andrew Garrison

2
@Ruben Bartelink: มันคืนค่า null ด้วย pointers เท่านั้น std::bad_castที่มีการอ้างอิงซึ่งคุณควรจะใช้เมื่อเป็นไปได้มันจะพ่น
Paddy

1
@Andrew Garrison: static_castไม่ทำการตรวจสอบประเภทรันไทม์ ไม่มีการบล็อกนี้ใน C #
Paddy พ่อ

น่าเศร้าที่ฉันไม่รู้ว่าคุณสามารถใช้งาน cast ได้กับการอ้างอิงเพราะฉันเคยใช้พวกมันกับพอยน์เตอร์ แต่ P Daddy นั้นถูกต้องจริงๆ!
Andrew Garrison

1

อาจเป็นที่นิยมมากขึ้นโดยไม่มีเหตุผลทางเทคนิค แต่เป็นเพราะง่ายต่อการอ่านและใช้งานง่ายขึ้น (ไม่ได้บอกว่าทำให้ดีกว่าเพียงแค่พยายามตอบคำถาม)


1

เหตุผลหนึ่งที่ใช้ "เป็น":

T t = obj as T;
 //some other thread changes obj to another type...
if (t != null) action(t); //still works

แทน (รหัสไม่ดี):

if (obj is T)
{
     //bang, some other thread changes obj to another type...
     action((T)obj); //InvalidCastException
}

2
หากคุณมีการแข่งขันที่น่าเกลียดนี้คุณมีปัญหาที่ใหญ่กว่า (แต่เห็นด้วยมันเป็นตัวอย่างที่ดีที่จะไปกับคนอื่นดังนั้น +1
Ruben Bartelink

-1 เนื่องจากสิ่งนี้จะทำให้เกิดการเข้าใจผิด หากเธรดอื่นสามารถเปลี่ยนประเภทของ obj ได้แสดงว่าคุณยังมีปัญหาอยู่ การอ้างสิทธิ์ "// ยังคงใช้งานได้" เป็นสิ่งที่ไม่น่าเป็นไปได้มากที่จะถือเป็นจริงเนื่องจาก t จะใช้เป็นตัวชี้ไปยัง T แต่ชี้ไปที่หน่วยความจำซึ่งไม่ใช่โซลูชัน T ทั้งสองจะทำงานเมื่อเธรดอื่นเปลี่ยนชนิดของ obj ขณะกำลังดำเนินการ (t)
สตีเฟ่นซี. เหล็ก

5
@ สตีเฟ่นซีเหล็ก: คุณดูเหมือนจะค่อนข้างสับสน การเปลี่ยนชนิดของobjจะหมายถึงการเปลี่ยนobjตัวแปรเพื่อเก็บการอ้างอิงไปยังวัตถุอื่น objมันจะไม่เปลี่ยนแปลงเนื้อหาของหน่วยความจำที่อยู่วัตถุอ้างอิงเดิมโดย วัตถุต้นฉบับนี้จะยังคงไม่เปลี่ยนแปลงและtตัวแปรจะยังคงมีการอ้างอิงถึงมัน
Paddy พ่อ


1
@P Daddy - ฉันคิดว่าคุณถูกต้องและฉันผิด: ถ้า obj ถูกเด้งจากวัตถุ T เป็นวัตถุ T2 แล้ว t จะยังคงชี้ไปที่วัตถุ T เก่า เนื่องจากยังคงอ้างอิงถึงวัตถุเก่าจึงไม่สามารถรวบรวมขยะได้ดังนั้นวัตถุ T เก่าจะยังคงใช้ได้ วงจรตัวตรวจจับสภาพการแข่งขันของฉันได้รับการฝึกฝนใน C ++ โดยที่โค้ดที่คล้ายกันโดยใช้ dynamic_cast จะเป็นปัญหาที่อาจเกิดขึ้น
สตีเฟ่นซีสตีล
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.