2015-04-27 25 views
8

Trong Haskell, có hai cách để cung cấp bí danh cho các loại: typenewtype. type cung cấp một loại từ đồng nghĩa, có nghĩa là từ đồng nghĩa được coi bởi các kiểm tra kiểu như giống hệt nhau như các loại bản gốc:C# tương đương với kiểu mới của Haskell là gì?

type UserId = Int 
hasAccess :: UserId -> Bool 
hasAccess id = {-- stuff --} 

-- Elsewhere in the program 
login :: Int -> Bool 
login n = hasAccess n -- Typechecker won't complain 

Một newtype là tương tự, nhưng được coi bởi các kiểm tra loại như một loại khác nhau :

newtype UserId = UserId Int 
hasAccess :: UserId -> Bool 
hasAccess (UserId id) = {-- stuff --} 

-- Elsewhere in the program 
login :: Int -> Bool 
login n = hasAccess n -- Typechecker will complain, n isn't a UserId ! 

Trong C#, bạn có thể xác định từ đồng nghĩa loại với cấp cao nhất using khai:

using UserId = Int; 

Tuy nhiên, một bí danh loại được kiểm tra theo trình biên dịch mạnh mẽ dường như không có mặt trong C# theo mặc định. Tôi đã xem xét việc tạo mã tự động với các mẫu T4 và CodeDOM để tạo ra một trình bao bọc lớp, nhưng tôi không thực sự biết làm thế nào tôi có thể tích hợp một cách rõ ràng những luồng đó vào luồng lập trình của tôi.

Lý tưởng nhất, tôi muốn để có thể nói về một cấp cao nhất:

// Something like this? 
using Int.UserId; 

/* Elsewhere */ 
var id = new UserId(5); 

public bool HasAccess(UserId id) 
{ 
    /* Stuff */ 
} 

này đá các thế hệ mã vào bánh tại thời gian biên dịch. Nếu đó là không thể hoặc cung cấp một vấn đề gà và trứng cho IntelliSense, một tùy chọn biên dịch tự động chạy mỗi x phút (hoặc một nút hoặc bất cứ điều gì) sẽ được tốt đẹp.

+2

Bạn có thể cung cấp một số thông tin cơ bản về lý do bạn muốn thực hiện việc này không? –

+0

Tại sao bạn muốn biên dịch mã của mình sau mỗi x phút? – Georg

+1

Việc sử dụng loại giấu dưới tên loại khác là gì? – Franck

Trả lời

13

Không, C# không có tính năng như vậy. Gần nhất bạn có thể nhận được để điều này là cấu trúc.

public struct UserId 
{ 
    public int Id { get; private set; } 

    public UserId(int id) : this() { Id = id; } 
} 

Bằng cách này, trình biên dịch thực sự đối xử với UserIdint loại như khác nhau. Hơn nữa, bạn có thể thêm các phương thức khác vào UserId có ý nghĩa với thực tế là int của bạn thực sự là một id người dùng. Lưu ý rằng điều này không có bất kỳ ảnh hưởng nào đến thời gian chạy, sử dụng một cấu trúc với một trường int đơn lẻ không gây ra bất kỳ chi phí nào đối với việc sử dụng trực tiếp int.

Chỉnh sửa: Vì bạn đã hỏi về T4, nếu bạn đang làm việc với Visual Studio, bạn có thể dễ dàng tạo mẫu văn bản T4 mới sẽ mở rộng thành (C#) - mã và sẽ được biên dịch tự động. Mẫu sẽ được thực hiện mỗi khi bạn lưu nó.

+1

Một điều quan trọng về newtypes trong Haskell là chúng là một sự trừu tượng rất rẻ (trên thực tế chúng được tối ưu hóa hoàn toàn sau khi kiểm tra kiểu). Trong ý nghĩa này, quá, cấu trúc là câu trả lời đúng. – kqr

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