2012-01-13 47 views
67

Tôi đã thấy cả hai thuật ngữ được sử dụng gần như thay thế cho nhau trong các giải thích trực tuyến khác nhau và hầu hết các sách giáo khoa tôi đã tham khảo cũng không hoàn toàn rõ ràng về sự khác biệt.Sự khác biệt giữa đúc và co giật là gì?

Có lẽ một cách rõ ràng và đơn giản để giải thích sự khác biệt mà các bạn biết không?

Loại chuyển đổi (cũng đôi khi được gọi là loại cast)

Để sử dụng một giá trị của một loại trong một bối cảnh mà hy vọng khác.

loại Nonconverting đúc (đôi khi được gọi là kiểu chơi chữ)

Một sự thay đổi đó không làm thay đổi các bit nằm bên dưới.

Cưỡng chế

Process mà một trình biên dịch tự động chuyển đổi một giá trị của một loại thành một giá trị kiểu khác khi mà loại thứ hai là yêu cầu của bối cảnh xung quanh.

+4

Điều gì về [bài viết trên Wikipedia] (http://en.wikipedia.org/wiki/Type_conversion)? –

Trả lời

83

Type Conversion:

Từ chuyển đổi đề cập đến một trong hai ngầm hay rõ ràng thay đổi một giá trị từ một kiểu dữ liệu khác, ví dụ số nguyên 16 bit đến số nguyên 32 bit.

Từ cưỡng chế được sử dụng để biểu thị một chuyển đổi tiềm ẩn.

Từ cast thường đề cập đến một chuyển đổi loại rõ ràng (trái với chuyển đổi ngầm), bất kể đây là giải thích lại mẫu bit hay chuyển đổi thực.

Vì vậy, sự ép buộc là ngầm định, diễn viên rõ ràng và chuyển đổi là bất kỳ từ khóa nào trong số đó.


vài ví dụ (từ same source):

Cưỡng chế (ngầm):

double d; 
int  i; 
if (d > i)  d = i; 

Cast (rõ ràng):

double da = 3.3; 
double db = 3.3; 
double dc = 3.4; 
int result = (int)da + (int)db + (int)dc; //result == 9 
+0

điều này sẽ làm cho "ép buộc ngầm" dư thừa? lưu ý [ở đây] (http://www.postgresql.org/docs/8.4/static/functions-string.html) sử dụng cả "cưỡng chế ngầm" và "cưỡng chế rõ ràng" –

+0

Chuyển đổi ngầm định chỉ có thể được thực hiện khi bạn không mất chính xác hoặc có ý nghĩa (Ví dụ: Int -> double). Trong ngôn ngữ hiện đại nhất, bạn không thể làm double-> int bởi vì bạn sẽ mất độ chính xác. Với sự ép buộc kiểu, đó không phải là một "vấn đề". –

6

Đúc là quá trình mà bạn đối xử với loại đối tượng dưới dạng loại khác, Cocing đang chuyển đổi một đối tượng này sang đối tượng khác. Lưu ý rằng trong quá trình trước đây không có chuyển đổi liên quan, bạn có một kiểu mà bạn muốn đối xử với nhau, ví dụ, bạn có 3 đối tượng khác nhau kế thừa từ một kiểu cơ sở, và bạn có một phương thức sẽ lấy kiểu cơ sở đó, tại bất kỳ điểm nào, nếu bây giờ là kiểu con cụ thể, bạn có thể CAST nó vào nó là gì và sử dụng tất cả các phương thức và thuộc tính cụ thể của đối tượng đó và sẽ không tạo ra một thể hiện mới của đối tượng. Mặt khác, co giật ngụ ý việc tạo ra một đối tượng mới trong bộ nhớ của kiểu mới và sau đó kiểu gốc sẽ được sao chép sang kiểu mới, để lại cả hai đối tượng trong bộ nhớ (cho đến khi Bộ gom rác lấy hoặc là đi , hoặc cả hai).

+1

Ví dụ sẽ giúp làm rõ sự khác biệt mà bạn đang cố gắng thực hiện. –

+0

Tôi mặc dù về ví dụ và nhận được với nó ngay lập tức;) – PedroC88

1

Dưới đây là một đăng từ following article:

Sự khác biệt giữa ép buộc và đúc thường bị bỏ qua. Tôi có thể thấy tại sao; nhiều ngôn ngữ có cú pháp và thuật ngữ giống nhau (hoặc tương tự) cho cả hai thao tác. Một số ngôn ngữ thậm chí có thể đề cập đến bất kỳ chuyển đổi nào là "truyền", nhưng giải thích sau đây đề cập đến các khái niệm trong CTS.

Nếu bạn đang cố gán giá trị của một loại nào đó cho một vị trí thuộc một loại khác, bạn có thể tạo ra một giá trị của loại mới có ý nghĩa tương tự với bản gốc. Đây là sự ép buộc. Coercion cho phép bạn sử dụng kiểu mới bằng cách tạo một giá trị mới theo cách nào đó giống với bản gốc. Một số coercions có thể loại bỏ dữ liệu (ví dụ: chuyển đổi int 0x12345678 thành 0x5678 ngắn), trong khi một số khác có thể không (ví dụ: chuyển đổi int 0x00000008 thành 0x0008 ngắn hoặc 0x0000000000000008 dài).

Nhớ lại rằng các giá trị có thể có nhiều loại. Nếu tình huống của bạn hơi khác và bạn chỉ muốn chọn một loại khác của các loại giá trị, việc truyền là công cụ cho công việc. Truyền đơn giản chỉ ra rằng bạn muốn vận hành trên một kiểu cụ thể mà một giá trị bao gồm.

Sự khác biệt ở cấp mã thay đổi từ C# đến IL. Trong C#, cả đúc và ép buộc trông khá tương tự:

static void ChangeTypes(int number, System.IO.Stream stream) 
{ 
    long longNumber = number; 
    short shortNumber = (short)number; 

    IDisposable disposableStream = stream; 
    System.IO.FileStream fileStream = (System.IO.FileStream)stream; 
} 

Ở cấp độ IL chúng hoàn toàn khác:

ldarg.0 
conv.i8 
stloc.0 

ldarg.0 
conv.i2 
stloc.1 


ldarg.1 
stloc.2 

ldarg.1 
castclass [mscorlib]System.IO.FileStream 
stloc.3 

Đối với mức độ hợp lý, có một số khác biệt quan trọng. Điều quan trọng nhất cần nhớ là việc ép buộc tạo ra một giá trị mới, trong khi quá trình truyền thì không. Danh tính của giá trị ban đầu và giá trị sau khi truyền đều giống nhau, trong khi danh tính của giá trị bị ép buộc khác với giá trị ban đầu; coersion tạo ra một cá thể mới, khác biệt, trong khi đúc thì không. Một hệ quả là kết quả của việc đúc và bản gốc sẽ luôn luôn là tương đương (cả về bản sắc và bình đẳng), nhưng giá trị bị ép buộc có thể hoặc không thể bằng với bản gốc, và không bao giờ chia sẻ bản sắc gốc.

Thật dễ dàng để xem các tác động của cưỡng chế trong các ví dụ ở trên, vì các loại số luôn được sao chép theo giá trị. Mọi thứ trở nên phức tạp hơn một chút khi bạn làm việc với các loại tham chiếu.

class Name : Tuple<string, string> 
{ 
    public Name(string first, string last) 
     : base(first, last) 
    { 
    } 

    public static implicit operator string[](Name name) 
    { 
     return new string[] { name.Item1, name.Item2 }; 
    } 
} 

Trong ví dụ dưới đây, một chuyển đổi là một diễn viên, trong khi chuyển đổi khác là một sự ép buộc.

Tuple<string, string> tuple = name; 
string[] strings = name; 

Sau khi chuyển đổi này, tên và tên bằng nhau, nhưng các chuỗi không bằng một trong hai. Bạn có thể làm cho tình huống tốt hơn một chút (hoặc hơi khó hiểu hơn) bằng cách thực hiện Equals() và toán tử ==() trên lớp Name để so sánh một Name và một chuỗi [].Những toán tử này sẽ “sửa” vấn đề so sánh, nhưng bạn vẫn sẽ có hai trường hợp riêng biệt; bất kỳ sửa đổi nào đối với các chuỗi sẽ không được phản ánh trong tên hoặc bộ, trong khi các thay đổi đối với một trong hai tên hoặc tuple sẽ được phản ánh trong tên và bộ, nhưng không được ghi trong chuỗi. Mặc dù ví dụ trên có nghĩa là minh họa một số khác biệt giữa việc ép và ép buộc, nó cũng là một ví dụ tuyệt vời về lý do bạn nên thận trọng khi sử dụng toán tử chuyển đổi với các kiểu tham chiếu trong C#.

20

Sử dụng khác nhau, như bạn lưu ý.

tập quán cá nhân của tôi là:

  • A "diễn viên" là việc sử dụng của một nhà điều hành cast. Một toán tử cast chỉ thị cho trình biên dịch rằng (1) biểu thức này không được biết là thuộc kiểu đã cho, nhưng tôi hứa với bạn rằng giá trị sẽ là kiểu đó khi chạy; trình biên dịch là để xử lý các biểu thức như là của các loại nhất định, và thời gian chạy sẽ tạo ra một lỗi nếu nó không phải là, hoặc (2) biểu thức là một loại khác nhau hoàn toàn, nhưng có một cách nổi tiếng để liên kết các trường hợp của loại biểu thức với các trường hợp của kiểu truyền đến. Trình biên dịch được hướng dẫn để tạo mã thực hiện chuyển đổi. Người đọc chu đáo sẽ lưu ý rằng đây là những đối lập, mà tôi nghĩ là một thủ thuật gọn gàng.

  • Một "chuyển đổi" là một hoạt động mà giá trị của một loại được coi là giá trị của loại khác - thường là loại khác, mặc dù "chuyển đổi nhận dạng" vẫn là chuyển đổi. Việc chuyển đổi có thể là "thay đổi biểu diễn", như int để tăng gấp đôi, hoặc nó có thể là "bảo quản đại diện" như chuỗi đối tượng. Chuyển đổi có thể là "ẩn", không yêu cầu dàn diễn viên hoặc "rõ ràng", yêu cầu dàn diễn viên.

  • "cưỡng chế" là chuyển đổi ngầm định thay đổi biểu diễn.

+0

Tôi nghĩ câu đầu tiên của câu trả lời này là điều quan trọng nhất. Các ngôn ngữ khác nhau sử dụng các thuật ngữ này để có nghĩa là những điều khá khác nhau. Trong Haskell, ví dụ, một "cưỡng chế" * không bao giờ * thay đổi đại diện; một sự ép buộc an toàn, 'Data.Coerce.coerce :: Coercible a b => a -> b' hoạt động cho các loại được chứng minh có cùng biểu diễn; 'Unsafe.Coerce.unsafeCoerce :: a -> b' làm việc cho bất kỳ hai loại (và sẽ làm cho ma quỷ đi ra khỏi mũi của bạn nếu bạn sử dụng nó sai). – dfeuer

+0

@dfeuer điểm dữ liệu thú vị, cảm ơn! Tôi lưu ý rằng thông số C# không xác định "cưỡng chế"; đề nghị của tôi chỉ là ý nghĩa cá nhân của tôi. Do thuật ngữ đó có vẻ kém, tôi thường tránh nó. –

Các vấn đề liên quan