วิธีที่ดีกว่าในการร่ายวัตถุไปยัง int


179

นี่อาจเป็นเรื่องเล็กน้อย แต่ฉันไม่สามารถคิดวิธีที่ดีกว่าที่จะทำ ฉันมีวัตถุ COM ที่คืนค่าตัวแปรซึ่งกลายเป็นวัตถุใน C # วิธีเดียวที่ฉันจะได้รับสิ่งนี้คือ int

int test = int.Parse(string.Format("{0}", myobject))

มีวิธีที่สะอาดกว่านี้หรือไม่? ขอบคุณ

คำตอบ:


362

คุณมีหลายทางเลือก:

  • (int)- ผู้ประกอบการหล่อ ใช้งานได้ถ้าวัตถุนั้นเป็นจำนวนเต็มในบางระดับในลำดับชั้นการสืบทอดหรือหากมีการกำหนดการแปลงโดยนัย

  • int.Parse()/int.TryParse() - สำหรับการแปลงจากสตริงของรูปแบบที่ไม่รู้จัก

  • int.ParseExact()/int.TryParseExact() - สำหรับการแปลงจากสตริงในรูปแบบเฉพาะ

  • Convert.ToInt32() - สำหรับการแปลงวัตถุประเภทที่ไม่รู้จัก มันจะใช้การแปลงที่ชัดเจนและโดยนัยหรือการใช้งาน IConvertible หากมีการกำหนดไว้

  • as int?- หมายเหตุเครื่องหมาย "?" asผู้ประกอบการเป็นเพียงสำหรับประเภทของการอ้างอิงและดังนั้นผมจึงใช้ "?" Nullable<int>จะมีความหมายว่า "การasดำเนินการ" ทำงานเหมือนConvert.To____()แต่คิดว่าTryParse()แทนที่จะParse(): มันกลับnullมากกว่าการขว้างปายกเว้นถ้าแปลงล้มเหลว

ของเหล่านี้ฉันต้องการ(int)ถ้าวัตถุเป็นเพียงจำนวนเต็มชนิดบรรจุกล่อง มิฉะนั้นจะใช้Convert.ToInt32()ในกรณีนี้

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


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

นักแสดงโดยตรงจะทำงานกับการแปลงโดยนัยหรือไม่ ฉันรู้สึกว่าจะทำ unboxing อย่างเคร่งครัดเท่านั้นไม่ใช่การแปลงอื่น ๆ
Darren Clark

ไม่ใช่คำตอบที่แน่ชัด แต่อ่านสิ่งนี้: blogs.msdn.com/ericlippert/archive/2009/03/19/ …
Joel Coehoorn

ผลที่สุดคือการที่มันทำได้มากกว่าการยกเลิกกล่อง มิฉะนั้นทำไมคุณถึงใช้มันเพื่อแปลงค่า double เป็น int ตัวอย่างเช่น
Joel Coehoorn

และอ่านสิ่งอื่น ๆ ที่ฉันอาจมีนัย / ชัดเจนของฉันย้อนกลับไปที่นั่น - แต่อย่างใดฉันคิดว่ามันได้รับจุดผ่าน
Joel Coehoorn

41

นักแสดง(int) myobject ควรจะทำงาน

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

เมื่อทำการร่ายบนชนิดค่าชนิดบรรจุกล่องจะใช้การร่ายแบบนั้นกับชนิดแบบบรรจุกล่องเท่านั้น ตัวอย่างของศัตรูถ้าตัวแปรที่ส่งคืนมาเป็น VT_I2 จริง ๆ แล้ว(int) (short) myObjectควรใช้งานได้

วิธีที่ง่ายที่สุดในการค้นหาคือตรวจสอบวัตถุที่ส่งคืนและดูประเภทของวัตถุนั้นในตัวดีบั๊ก นอกจากนี้ตรวจสอบให้แน่ใจว่าในแอสเซมบลี interop คุณมีเครื่องหมายส่งคืนค่าด้วยMarshalAs(UnmanagedType.Struct)


32

Convert.ToInt32 (MyObject);

กรณีนี้จะจัดการกับกรณีที่ myobject เป็นโมฆะและส่งคืน 0 แทนที่จะโยนข้อยกเว้น


ฉันได้รับ "ไม่สามารถแก้ไขสัญลักษณ์" ToInt "" เมื่อฉันลองแบบนี้ ToInt32มันจะทำงานเฉพาะถ้าใช้เช่น
Tobias Feil

เราจะหาวิธีนี้ได้ที่ไหน อยู่ใน. Net Framework Library หรือไม่
Amir Pourmand امیرپورمند

8

ใช้Int32.TryParseดังนี้

  int test;
  bool result = Int32.TryParse(value, out test);
  if (result)
  {
     Console.WriteLine("Sucess");         
  }
  else
  {
     if (value == null) value = ""; 
     Console.WriteLine("Failure");
  }

ที่จริงแล้ว Parse เรียกใช้ TryParse และส่งข้อยกเว้นถ้า TryParse ส่งคืนค่าเท็จ ดังนั้น TryParse จึงไม่สามารถจัดการข้อยกเว้นได้
ซามูเอล

ในทางเทคนิคแล้วพวกเขาทั้งสองเรียกเมธอดเดียวกัน NumberToInt32 แต่มีเพียง Parse เท่านั้นที่จะทำการยกเว้นเมื่อมันไม่ทำงาน
ซามูเอล

TryParse ยังต้องการการแปลงชุดอักขระเป็นสตริง AFAIK ปัญหาไม่ได้แปลงจากสตริงเป็น int แต่จากตัวแปรที่เป็น int ถึง int ที่แท้จริง
Darren Clark

3

ฉันแสดงความแตกต่างในแต่ละวิธีการคัดเลือก การหล่อแบบพิเศษนั้นจัดการกับอะไรและไม่ได้?

    // object to int
    // does not handle null
    // does not handle NAN ("102art54")
    // convert value to integar
    int intObj = (int)obj;

    // handles only null or number
    int? nullableIntObj = (int?)obj; // null
    Nullable<int> nullableIntObj1 = (Nullable<int>)obj; // null

   // best way for casting from object to nullable int
   // handles null 
   // handles other datatypes gives null("sadfsdf") // result null
    int? nullableIntObj2 = obj as int?; 

    // string to int 
    // does not handle null( throws exception)
    // does not string NAN ("102art54") (throws exception)
    // converts string to int ("26236")
    // accepts string value
    int iVal3 = int.Parse("10120"); // throws exception value cannot be null;

    // handles null converts null to 0
    // does not handle NAN ("102art54") (throws exception)
    // converts obj to int ("26236")
    int val4 = Convert.ToInt32("10120"); 

    // handle null converts null to 0
    // handle NAN ("101art54") converts null to 0
    // convert string to int ("26236")
    int number;

    bool result = int.TryParse(value, out number);

    if (result)
    {
        // converted value
    }
    else
    {
        // number o/p = 0
    }


2
var intTried = Convert.ChangeType(myObject, typeof(int)) as int?;

1
ฉันพบว่าคำตอบนี้มีประโยชน์จริง ๆ ฉันกำลังหาวิธีใส่ไบต์แบบกล่องลงใน int และนำไปใช้งานConvert.ChangeTypeได้ ฉันจะบอกว่าอาจไม่ใช่คำตอบที่สมบูรณ์แบบสำหรับ OP แต่มันมีประโยชน์กับบางคน!
Philippe Paré

1

นอกจากนี้ยังมีTryParse

จาก MSDN:

private static void TryToParse(string value)
   {
      int number;
      bool result = Int32.TryParse(value, out number);
      if (result)
      {
         Console.WriteLine("Converted '{0}' to {1}.", value, number);         
      }
      else
      {
         if (value == null) value = ""; 
         Console.WriteLine("Attempted conversion of '{0}' failed.", value);
      }
   }

1

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

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

อีกวิธีที่ง่าย แต่การคิดต้นทุนที่มีประสิทธิภาพจริงๆคือการสร้างมาก่อนในแบบไดนามิก

(int) (ไดนามิก) myObject

คุณสามารถลองได้ในหน้าต่างโต้ตอบของ VS

public class Test
{
  public static implicit operator int(Test v)
  {
    return 12;
  }
}

(int)(object)new Test() //this will fail
Convert.ToInt32((object)new Test()) //this will fail
(int)(dynamic)(object)new Test() //this will pass

1
นี่เป็นเรื่องจริงแต่เป็นสิ่งที่แน่นอนที่คุณต้องการโปรไฟล์ถ้าคุณทำมันมาก - dynamicอยู่ไกลจากฟรี
Marc Gravell

@ MarcGravell ฉันเห็นด้วยกับคุณโดยสิ้นเชิงในขณะที่ฉันเขียนไว้ในคำตอบ
eTomm

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