เมื่อใดจึงจะใช้ Cast () และ Oftype () ใน Linq


211

ฉันรับรู้ถึงวิธีการหล่อสองแบบIEnumerableจากArraylistใน Linq และสงสัยว่าจะใช้พวกเขาในกรณีใด

เช่น

IEnumerable<string> someCollection = arrayList.OfType<string>()

หรือ

IEnumerable<string> someCollection = arrayList.Cast<string>()

อะไรคือความแตกต่างระหว่างสองวิธีนี้และฉันควรใช้แต่ละกรณีอย่างไร

คำตอบ:


322

OfType- ส่งคืนเฉพาะองค์ประกอบที่สามารถร่ายได้อย่างปลอดภัยเพื่อพิมพ์ x
Cast- จะพยายามโยนองค์ประกอบทั้งหมดลงในประเภท x หากบางคนไม่ได้มาจากประเภทนี้คุณจะได้รับInvalidCastException


ตัวอย่างการแก้ไข :

object[] objs = new object[] { "12345", 12 };
objs.Cast<string>().ToArray(); //throws InvalidCastException
objs.OfType<string>().ToArray(); //return { "12345" }

1
ขอบคุณสำหรับสิ่งนั้น พยายามทั้งสองมาก่อน แต่ทั้งคู่มีองค์ประกอบทุกอย่างที่คาดไว้ดังนั้นทำไมฉันไม่เห็นความแตกต่าง

6
@SLaks ชี้ให้เห็นอย่างถูกต้องว่าคุณควรใช้Cast<T>เมื่อคุณรู้ว่าคอลเลกชันมีTองค์ประกอบประเภทเท่านั้น OfType<T>ช้าลงเนื่องจากการisตรวจสอบประเภท หากคอลเลกชันเป็นชนิดIEnumerable<T>, Cast<T>จะเหวี่ยงก็เก็บทั้งเป็นIEnumerable<T>และหลีกเลี่ยงแจงมัน OfType<T>จะยังคงระบุ อ้างอิง: stackoverflow.com/questions/11430570/…
hIpPy

23
แม้ในกรณีที่.Cast<string>()ไม่เคยโยนเมื่อมีการแจกแจงมันไม่.OfType<string>()เทียบเท่ากับ เหตุผลก็คือnullค่าต่างๆจะถูกข้ามโดย.OfType<TResult>()เสมอ ตัวอย่าง: new System.Collections.ArrayList { "abc", "def", null, "ghi", }.OfType<string>().Count()จะให้เพียง3; การแสดงออกในลักษณะเดียวกับประเมิน.Cast<string>() 4
Jeppe Stig Nielsen

1
กล่าวอีกอย่างหนึ่งก็คือความแตกต่างระหว่างโอเปอเรเตอร์แบบ 'as' และ 'cast'
faza

111

http://solutionizing.net/2009/01/18/linq-tip-enumerable-oftype/

พื้นฐาน Cast () มีการใช้งานเช่นนี้:

public IEnumerable<T> Cast<T>(this IEnumerable source)
{
  foreach(object o in source)
    yield return (T) o;
}

การใช้งาน cast ชัดเจนจะทำงานได้ดี แต่จะส่งผลให้ InvalidCastException หากการส่งล้มเหลว รูปแบบที่มีประสิทธิภาพน้อยกว่า แต่มีประโยชน์ในแนวคิดนี้คือ OfType ():

public IEnumerable<T> OfType<T>(this IEnumerable source)
{
  foreach(object o in source)
    if(o is T)
      yield return (T) o;
}

การแจงนับที่ส่งคืนจะมีเฉพาะองค์ประกอบที่สามารถส่งไปยังประเภทที่ระบุได้อย่างปลอดภัย


38

คุณควรโทรCast<string>()ถ้าคุณรู้ว่าสินค้าทั้งหมดเป็นstringของ
หากบางคนไม่ใช่สตริงคุณจะได้รับการยกเว้น

คุณควรโทรOfType<string>()ถ้าคุณรู้ว่าบางรายการไม่stringเป็นของและคุณไม่ต้องการรายการเหล่านั้น หากบางส่วนของพวกเขาไม่ได้เป็นเงื่อนไขที่พวกเขาจะไม่อยู่ในใหม่
IEnumerable<string>


1
คำตอบนี้ (ปัจจุบัน) คำตอบเดียวที่ให้คำแนะนำอย่างชัดเจนเมื่อใช้วิธีใด
CodeFox

4

ควรสังเกตว่าCast(Of T)สามารถใช้กับIEnumerableฟังก์ชั่นอื่น ๆ ของ LINQ ไม่ได้ดังนั้นหากมีกรณีที่คุณจำเป็นต้องใช้ LINQ ในคอลเลกชันที่ไม่ใช่แบบทั่วไปหรือรายการเช่นArrayListคุณสามารถใช้Cast(Of T)เพื่อส่งไปยังIEnumerable(Of T)ที่ที่ LINQ สามารถทำงานได้


2

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


2

OfTypeจะกรององค์ประกอบเพื่อคืนเฉพาะประเภทที่ระบุ Castจะล้มเหลวหากองค์ประกอบไม่สามารถส่งไปยังประเภทเป้าหมายได้


2

Cast<T>Tจะพยายามที่จะโยนทุกรายการประเภทที่กำหนด นักแสดงนี้อาจล้มเหลวหรือโยนข้อยกเว้น จะกลับมาส่วนหนึ่งของคอลเลกชันเดิมและกลับวัตถุเดียวที่เป็นประเภทOfType<T>T

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