เหตุใดฉันจึงผ่าน 1 เป็นตัวย่อ แต่ไม่ใช่ตัวแปร int i


146

ทำไมการเขียนครั้งแรกและครั้งที่สองถึงทำงาน แต่ไม่ใช่ครั้งสุดท้าย มีวิธีที่ฉันสามารถอนุญาตให้ทั้ง 3 คนและตรวจพบว่าเป็น 1, (int) 1 หรือฉันผ่านไปแล้วหรือไม่? และทำไมคนหนึ่งถึงได้รับอนุญาต แต่คนสุดท้าย? การได้รับอนุญาตครั้งที่สอง แต่ไม่ใช่ครั้งสุดท้ายที่พัดใจของฉัน

การสาธิตเพื่อแสดงข้อผิดพลาดในการคอมไพล์

using System;
class Program
{
    public static void Write(short v) { }
    static void Main(string[] args)
    {
        Write(1);//ok
        Write((int)1);//ok
        int i=1;
        Write(i);//error!?
    }
}

2
ฉันก็งงด้วยนี้ฉันมักจะต้อง ints ให้สั้นในการเรียกใช้ฟังก์ชันแม้ว่าพวกเขาควรจะ castable ...
Mathieu Dumoulin

2
@MathieuDumoulin พวกเขาหล่อได้นั่นเป็นเหตุผลที่คุณสามารถเลือกพวกเขาได้ แต่มันเป็นแปลง lossfull (มี ints จำนวนมากที่ไม่เหมาะสมในระยะสั้น) (short) iนำแสดงโดยปริยายดังนั้นเป็นไปไม่ได้ที่ว่าทำไมคุณต้องเขียน
Abel

คำตอบ:


186

สองรายการแรกเป็นนิพจน์คงที่ส่วนสุดท้ายไม่ใช่

ข้อมูลจำเพาะ C # อนุญาตให้มีการแปลงโดยนัยจาก int เป็น short สำหรับค่าคงที่ แต่ไม่ใช่สำหรับนิพจน์อื่น นี่เป็นกฎที่สมเหตุสมผลเนื่องจากสำหรับค่าคงที่คอมไพเลอร์สามารถมั่นใจได้ว่าค่าเหมาะสมกับประเภทเป้าหมาย แต่ไม่สามารถใช้กับนิพจน์ปกติได้

กฎนี้เป็นไปตามแนวทางที่ควรมีการสูญเสียการแปลงโดยนัย

6.1.8 การแปลงค่าคงที่ของนิพจน์โดยนัย

การแปลงค่าคงที่นิพจน์โดยนัยอนุญาตให้มีการแปลงต่อไปนี้:

  • คงแสดงออก (§7.18) ประเภทintสามารถแปลงเป็นประเภทsbyte, byte, short, ushort, uintหรือulongให้ค่าของค่าคงที่แสดงออกอยู่ในช่วงของประเภทปลายทาง
  • การแปลงค่าคงที่ของประเภทlongสามารถแปลงเป็นประเภทได้ulongโดยที่ค่าของการแสดงออกคงที่ไม่ได้เป็นค่าลบ

(ยกมาจาก C # Language Specification เวอร์ชั่น 3.0)


67

ไม่มีการแปลงโดยนัยจากintเป็นshortเพราะความเป็นไปได้ของการตัด แต่การแสดงออกคงสามารถรักษาได้เป็นประเภทเป้าหมายโดยรวบรวม

1? ไม่ใช่ปัญหา: เป็นshortค่าที่ถูกต้องชัดเจน i? ไม่มาก - อาจเป็นค่า> short.MaxValueตัวอย่างและคอมไพเลอร์ไม่สามารถตรวจสอบในกรณีทั่วไป


ดังนั้น ... มันไม่สำคัญว่าฉันจะชัดเจนแค่ไหน ... > _ < คุณมีความคิดใด ๆ ไหมถ้าฉันสามารถตรวจจับได้ว่ามีการส่งผ่านเรื่องราวหรือไม่หรือตัวแปร int?

@ acidzombie24 คุณไม่สามารถ แต่ทำไมคุณต้องการทำเช่นนั้น?
Adam Houldsworth

@ acidzombie24 ฉันไม่คิดว่าคุณจะตรวจจับได้ อย่างไรก็ตามคุณสามารถใช้อาร์กิวเมนต์เท็มเพลตจากนั้นใช้การสะท้อนเพื่อรับชนิดของมัน
Konrad Rudolph

3
@ acidzombie24 ไม่มีวิธีใดที่ตัวอักษรจะถูกส่งผ่านในระหว่างรันไทม์ ดังนั้นคุณสามารถใช้สายตาของคุณเพื่อตรวจสอบเวลารวบรวม
Justin

1
@ acidzombie24 ในกรณีนั้นมันจะเป็นตัวเลือกในการยอมรับการโต้แย้งว่าเป็นExpression<Func<int>>? จากนั้นคุณสามารถผ่าน() => 1หรือ() => iภายในฟังก์ชันที่คุณสามารถตรวจสอบได้ว่าเอนทิตีที่ส่งผ่านนั้นมีตัวแปรที่ถูกดักจับหรือค่าคงที่
Konrad Rudolph

8

int อักษรshortสามารถแปลงไปโดยปริยาย โดย:

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

ดังนั้นสองงานแรกเพราะอนุญาตให้มีการแปลงตัวอักษรโดยนัย


3
คำตอบของคุณผิดเล็กน้อย คุณไม่ควรใช้ตัวอักษรแต่คงแสดงออก โดยเฉพาะอย่างยิ่งตัวอย่างที่สองไม่ได้เป็นตัวอักษร
CodesInChaos

6

ฉันเชื่อว่าเป็นเพราะคุณผ่านตัวอักษร / ค่าคงที่ในสองคนแรก แต่ไม่มีการแปลงประเภทอัตโนมัติเมื่อผ่านจำนวนเต็มในที่สาม

แก้ไข: มีคนเอาชนะฉัน!


3

เนื่องจากจะไม่มีการแปลงโดยนัยใด ๆระหว่างประเภทที่ไม่ใช่ตัวอักษรเป็นขนาดใหญ่

การแปลงโดยนัยเป็นไปได้สำหรับการแสดงออกอย่างต่อเนื่องเท่านั้น

public static void Write(short v) { }

ในกรณีที่คุณกำลังผ่านintegerค่าเป็นข้อโต้แย้งไปshort

int i=1;
Write(i);  //Which is Nonliteral here

3

คอมไพเลอร์ได้บอกคุณว่าทำไมรหัสล้มเหลว:

cannot convert `int' expression to type `short'

ดังนั้นนี่คือคำถามที่คุณควรถาม: ทำไมการแปลงนี้จึงล้มเหลว ฉัน googled "c # convert int short" และลงเอยด้วยหน้า MS C # สำหรับshortคำค้นหา:

http://msdn.microsoft.com/en-us/library/ybs77ex4(v=vs.71).aspx

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

Write((short)i)

0

การแปลงจาก int -> short อาจทำให้ข้อมูลถูกตัดทอน นั่นเป็นเหตุผล

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