จะโยน Object ให้เป็นประเภทจริงได้อย่างไร?


121

ถ้าฉันมี:

void MyMethod(Object obj) {   ...   }

ฉันobjจะแคสให้เป็นประเภทที่แท้จริงได้อย่างไร?


2
ประเภทเป็นที่รู้จักในเวลาคอมไพล์หรือไม่?
psubsee2003

1
และสิ่งที่คุณคาดหวังว่าจะสำเร็จจากสิ่งนี้? โปรดบอกเราว่าคุณกำลังพยายามบรรลุอะไรมากกว่าที่คุณคาดหวังว่าจะบรรลุเป้าหมายนั้น
Jon Skeet

@JonSkeet: ฉันต้องการเรียกใช้ฟังก์ชันจากวัตถุ ขณะนี้obj.MyFunction();ไม่ได้รวบรวมแม้ว่าฉันจะรู้ว่าวัตถุจริงมีฟังก์ชันนั้น
Paul Lassiter

@ psubsee2003: ไม่ไม่เพราะเป็นการอ้างอิงวัตถุที่ส่งผ่านผ่าน interop
Paul Lassiter

3
@PaulLassiter: ถ้าคุณไม่ทราบประเภทสิ่งที่ประกาศMyFunctionวิธีการ?
Jon Skeet

คำตอบ:


194

หากคุณทราบประเภทที่แท้จริงให้ทำดังนี้

SomeType typed = (SomeType)obj;
typed.MyFunction();

หากคุณไม่ทราบประเภทที่แท้จริงแสดงว่าไม่จริงไม่ คุณจะต้องใช้หนึ่งใน:

  • การสะท้อน
  • การใช้อินเทอร์เฟซที่รู้จักกันดี
  • พลวัต

ตัวอย่างเช่น:

// reflection
obj.GetType().GetMethod("MyFunction").Invoke(obj, null);

// interface
IFoo foo = (IFoo)obj; // where SomeType : IFoo and IFoo declares MyFunction
foo.MyFunction();

// dynamic
dynamic d = obj;
d.MyFunction();

1
ไวยากรณ์ที่เทียบเท่าใน Swift คืออะไร?
Nagendra Rao

1
ไม่เป็นไรพบasสำหรับการพิมพ์และtype(of: ClassName)ฟังก์ชั่นในการตรวจสอบประเภทอินสแตนซ์
Nagendra Rao

43

ฉันไม่คิดว่าคุณทำได้ (ไม่ใช่โดยไม่ไตร่ตรอง) คุณควรระบุประเภทให้กับฟังก์ชันของคุณด้วย:

void MyMethod(Object obj, Type t)
{
    var convertedObject = Convert.ChangeType(obj, t);
    ...
}

UPD :

สิ่งนี้อาจเหมาะกับคุณ:

void MyMethod(Object obj)
{
    if (obj is A)
    {
        A a = obj as A;
        ...
    } 
    else if (obj is B)
    {
        B b = obj as B;
        ...
    }
}

4
นี่เป็นคำตอบที่ไร้ประโยชน์และไม่สมควรได้รับการโหวต การสะท้อนของวัตถุประเภทวัตถุจะไม่ให้ "ประเภทจริง" ของวัตถุดังที่ OP ถาม นอกจากนี้ตรรกะ MyMethod ของคุณยังมีข้อบกพร่องเนื่องจาก obj สามารถเป็นประเภท A และยังสามารถเป็นประเภท B ได้อีกด้วยตรรกะของคุณไม่ได้ระบุ "ประเภทจริง" (ตามที่ขอ OP) - เป็นประเภทที่เข้ากันได้และไม่จำเป็น ประเภทที่ต้องการได้เลย
Jazimov

ใช้ obj.GetType () แน่นอนว่าจะกลับมาเป็นประเภทที่แท้จริง
JSON

3

วิธีการเกี่ยวกับ JsonConvert.DeserializeObject (object ToString ());


นี่ไม่ใช่คำตอบที่น่าพึงพอใจ คำถามของ OP ไม่เกี่ยวข้องกับ Json หรือ serialization

@ user12637955 นี่เป็นคำตอบที่ใช้ได้จริง แต่มีความซับซ้อนมากกว่าเนื่องจากการชกมวยและการแกะกล่องเช่น object -> ToString () -> เป็นคอนกรีต เพื่อให้แม่นยำยิ่งขึ้นควรมีลักษณะดังนี้var myType = JsonConvert.DeserializeObject<MyType>(object.ToString());
โค้ก

1

ในกรณีของฉัน AutoMapper ทำงานได้ดี

AutoMapper สามารถแมปไปยัง / จากวัตถุแบบไดนามิกโดยไม่มีการกำหนดค่าที่ชัดเจน:

public class Foo {
    public int Bar { get; set; }
    public int Baz { get; set; }
}
dynamic foo = new MyDynamicObject();
foo.Bar = 5;
foo.Baz = 6;

Mapper.Initialize(cfg => {});

var result = Mapper.Map<Foo>(foo);
result.Bar.ShouldEqual(5);
result.Baz.ShouldEqual(6);

dynamic foo2 = Mapper.Map<MyDynamicObject>(result);
foo2.Bar.ShouldEqual(5);
foo2.Baz.ShouldEqual(6);

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

ข้อมูลเพิ่มเติมhttps://github.com/AutoMapper/AutoMapper/wiki/Dynamic-and-ExpandoObject-Mapping


1

วิธีนี้อาจไม่ได้ผลดีที่สุด แต่ทำได้ง่ายและได้ผล

ดำเนินการสองอย่าง: ประการแรกเรียกว่า. ToString () ซึ่งเป็นพื้นฐานของการทำให้เป็นอนุกรมจากนั้นจึงทำการแยกสารโดยใช้ Newtonsoft nuget (ซึ่งคุณต้องติดตั้ง)

public T Format<T>(Object obj) =>
    JsonConvert.DeserializeObject<T>(obj.ToString());

คุณควรอธิบายคำตอบของคุณสั้น ๆ สำหรับผู้อ่านในอนาคต
Suraj Kumar

0

ถ้าMyFunction()เมธอดของคุณถูกกำหนดไว้ในคลาสเดียวเท่านั้น (และสืบทอด) ให้ลอง

void MyMethod(Object obj) 
{
    var o = obj as MyClass;
    if (o != null)
        o.MyFunction();
}

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

interface IMyInterface
{
    void MyFunction();
}

void MyMethod(Object obj) 
{
    var o = obj as IMyInterface;
    if (o != null)
        o.MyFunction();
}

0

แคสต์ให้เป็นประเภทจริงถ้าคุณเป็นประเภทเช่นตอนนี้เป็นประเภทที่มุ่งเน้นจากคลาสชื่อ abc คุณสามารถเรียกใช้ฟังก์ชันของคุณด้วยวิธีนี้:

(abc)(obj)).MyFunction();

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


-1

การแคสต์เป็นประเภทจริงทำได้ง่าย:

void MyMethod(Object obj) {
    ActualType actualyType = (ActualType)obj;
}

8
นี่คือเหตุผล คุณไม่ทราบประเภทที่แท้จริง คุณควรจะทำอย่างไร?
Allen Linatoc

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