Tại sao tôi có thể vượt qua 1 dưới dạng ngắn, nhưng không phải là biến int i?


146

Tại sao Viết đầu tiên và thứ hai hoạt động nhưng không phải là cuối cùng? Có cách nào tôi có thể cho phép cả 3 người trong số họ và phát hiện nếu đó là 1, (int) 1 hoặc tôi đã truyền vào không? Và thực sự tại sao một người được phép nhưng cuối cùng? Cái thứ hai được cho phép nhưng không phải cái cuối cùng thực sự làm tôi suy nghĩ.

Bản trình diễn để hiển thị lỗi biên dịch

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
Tôi cũng bị bối rối bởi điều này, tôi thường phải thực hiện các cuộc gọi ngắn gọn trong các cuộc gọi chức năng mặc dù chúng có thể được đúc ...
Mathieu Dumoulin

2
@MathieuDumoulin chúng có thể đúc được, đó là lý do tại sao bạn có thể sử dụng chúng. Nhưng đó là một chuyển đổi mất mát (có nhiều số nguyên không phù hợp trong một thời gian ngắn), vì vậy diễn viên ngầm là không thể, đó là lý do tại sao bạn phải viết (short) i.
Abel

Câu trả lời:


186

Hai cái đầu tiên là biểu thức không đổi, cái cuối cùng thì không.

Đặc tả C # cho phép chuyển đổi ngầm định từ int sang short cho các hằng, nhưng không cho các biểu thức khác. Đây là một quy tắc hợp lý, vì đối với các hằng số, trình biên dịch có thể đảm bảo rằng giá trị phù hợp với loại mục tiêu, nhưng nó không thể cho các biểu thức bình thường.

Quy tắc này phù hợp với hướng dẫn rằng chuyển đổi ngầm định sẽ không bị mất.

6.1.8 Chuyển đổi biểu thức hằng liên tục

Chuyển đổi biểu thức hằng liên tục ẩn cho phép các chuyển đổi sau:

  • Một liên tục thể hiện (§7.18) loại intcó thể được chuyển đổi sang loại sbyte, byte, short, ushort, uint, hay ulong, với điều kiện giá trị của hằng số thể hiện nằm trong phạm vi của các loại đích.
  • Một hằng số thể hiện kiểu longcó thể được chuyển đổi sang loại hình ulong, với điều kiện giá trị của hằng số thể hiện không phải là tiêu cực.

(Trích dẫn từ Đặc tả ngôn ngữ C # Phiên bản 3.0)


67

Không có chuyển đổi ngầm từ intsang shortvì khả năng cắt ngắn. Tuy nhiên, một biểu thức hằng có thể được coi là thuộc loại đích của trình biên dịch .

1? Không phải là một vấn đề: nó rõ ràng là một giá shorttrị hợp lệ . i? Không quá nhiều - chẳng hạn có thể là một số giá trị> short.MaxValuevà trình biên dịch không thể kiểm tra điều đó trong trường hợp chung.


Vì vậy, ... không quan trọng tôi rõ ràng như thế nào ...> _ <. Bạn có bất cứ ý tưởng nếu tôi có thể phát hiện nếu một văn học đã được thông qua hoặc một biến int?

@ acidzombie24 Bạn không thể. Nhưng tại sao bạn lại muốn làm điều đó?
Adam Houldsworth

@ acidzombie24 Tôi không nghĩ bạn có thể phát hiện ra điều đó. Tuy nhiên, bạn có thể sử dụng một đối số mẫu và sau đó sử dụng sự phản chiếu để có được kiểu của nó.
Konrad Rudolph

3
@ acidzombie24 Không có cách nào một nghĩa đen có thể được thông qua trong thời gian chạy. Vì vậy, bạn chỉ có thể sử dụng đôi mắt của bạn để kiểm tra tại thời gian biên dịch.
Justin

1
@ acidzombie24 Trong trường hợp đó, nó có phải là một lựa chọn để chấp nhận đối số là một Expression<Func<int>>? Sau đó, bạn có thể vượt qua () => 1hoặc () => ibên trong hàm bạn có thể kiểm tra xem thực thể được truyền có chứa biến bị bắt hay giá trị không đổi.
Konrad Rudolph

8

một int nghĩa đen có thể được chuyển đổi hoàn toàn thành short. Trong khi:

Bạn không thể ngầm chuyển đổi các loại số không theo tiêu chuẩn có kích thước lưu trữ lớn hơn thành ngắn

Vì vậy, hai công việc đầu tiên vì chuyển đổi ngầm định của chữ được cho phép.


3
Câu trả lời của bạn hơi sai. Bạn không nên sử dụng biểu thức bằng chữ nhưng không đổi . Cụ thể, ví dụ thứ hai không phải là nghĩa đen .
CodeInChaos

6

Tôi tin rằng đó là bởi vì bạn đang chuyển một chữ / hằng trong hai số đầu tiên, nhưng không có chuyển đổi loại tự động khi chuyển một số nguyên trong phần ba.

Chỉnh sửa: Ai đó đánh tôi với nó!


3

Bởi vì sẽ không có bất cứ ngầm chuyển đổi giữa Nonliteral loại để ngắn kích thước lớn hơn.

Chuyển đổi ngầm định chỉ có thể cho biểu thức không đổi.

public static void Write(short v) { }

Khi bạn đang chuyển integergiá trị làm đối số choshort

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

3

Trình biên dịch đã cho bạn biết lý do tại sao mã bị lỗi:

cannot convert `int' expression to type `short'

Vì vậy, đây là câu hỏi bạn nên đặt ra: tại sao việc chuyển đổi này thất bại? Tôi đã googled "c # convert int short" và kết thúc trên trang MS C # cho shorttừ khóa:

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

Như trang này nói, các hàm ẩn từ một loại dữ liệu lớn hơn shortchỉ được phép cho chữ. Trình biên dịch có thể biết khi nào một nghĩa đen nằm ngoài phạm vi, nhưng không phải vậy, do đó, cần phải đảm bảo rằng bạn đã tránh được một lỗi ngoài phạm vi trong logic chương trình của bạn. Sự yên tâm đó được cung cấp bởi một diễn viên.

Write((short)i)

0

Chuyển đổi từ int -> ngắn có thể dẫn đến việc cắt dữ liệu. Đó là lý do tại sao.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.