2015-04-27 80 views
8

在Haskell中,有兩種爲類型提供別名的方法:typenewtypetype提供類型同義詞,這意味着同義詞由類型檢查器視爲完全相同的原始類型:什麼是C#相當於Haskell的新類型?

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

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

newtype是類似的,但由類型檢查器視爲不同類型的:

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 ! 

在C#中,您可以定義類型的同義詞頂級using聲明:

using UserId = Int; 

但是,缺省情況下,C#中似乎沒有強類型的,編譯器檢查的類型別名。我已經研究了使用T4模板和CodeDOM生成自動代碼生成以生成類封裝器,但我不知道如何將它們完全集成到我的編程流程中。

理想情況下,我希望能夠在頂級說:

// Something like this? 
using Int.UserId; 

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

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

這踢的代碼生成到齒輪在編譯時。如果這不可能或爲智能感知提供雞與雞的問題,每運行一分鐘(或一個按鈕或其他)的自動編譯選項將會很好。

+2

你能提供一些你爲什麼要這樣做的背景嗎? –

+0

你爲什麼要每x分鐘編譯一次你的代碼? – Georg

+1

在另一個類型名稱下隱藏一個類型有什麼用處? – Franck

回答

13

不,C#沒有這樣的功能。最接近你的是結構。

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

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

這樣,編譯器確實把UserIdint爲不同的類型。此外,您可以在UserId中添加更多方法,因爲您的int實際上是用戶標識。同樣需要注意的是,這對運行時沒有任何影響,使用帶有單個int的結構體字段不會導致直接使用int的任何開銷。因爲您詢問了T4,如果您使用的是Visual Studio,則可以輕鬆創建一個新的T4文本模板,該模板將展開爲(C#) - 代碼並自動進行編譯。每次保存時都會執行該模板。

+1

關於Haskell中新類型的一個重要事情是它們是一個非常便宜的抽象(實際上它們在類型檢查後被完全優化)。在這個意義上,結構也是正確的答案。 – kqr

相關問題