什么是C#相当于Haskell的新类型?

时间:2015-04-27 11:18:07

标签: c# haskell newtype

在Haskell中,有两种方法可以为类型提供别名:typenewtypetype提供类型同义词,这意味着类型检查器将同义词视为与原始类型完全相同:

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 */
}

这将代码生成在编译时启动 。如果这不可能或者为IntelliSense提供鸡蛋和鸡蛋问题,那么每隔 x 分钟(或按钮或其他)运行的自动编译选项会很不错。

1 个答案:

答案 0 :(得分:15)

不,C#没有这样的功能。你最接近的就是结构。

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

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

这样,编译器确实将UserIdint视为不同的类型。此外,您可以向UserId添加更多有用的方法,因为您的int实际上是用户ID。另请注意,这对运行时没有任何影响,使用带有单个int字段的结构不会导致直接使用int的任何开销。

编辑:因为您询问了T4,如果您正在使用Visual Studio,您可以轻松创建一个新的T4文本模板,该模板将扩展为(C#) - 代码并将自动编译。每次保存时都会执行模板。