简体   繁体   English

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

[英]What is C#'s equivalent to Haskell's newtype?

In Haskell, there's two ways of providing an alias for types: type and newtype . 在Haskell中,有两种方法可以为类型提供别名: typenewtype type provides a type synonym , which means the synonym is regarded by the type checker as exactly the same as the original type: type提供类型同义词 ,这意味着类型检查器将同义词视为与原始类型完全相同:

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

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

A newtype is similar, but is regarded by the type checker as a different type: 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 !

In C#, you can define type synonyms with a top-level using declaration: 在C#中,您可以使用顶级using声明来定义类型同义词:

using UserId = Int;

However, a strongly-typed, compiler-checked type alias does not seem to be present in C# by default. 但是,默认情况下,C#中似乎不存在强类型的编译器检查类型别名。 I've looked into automatic code generation with T4 templates and CodeDOM to generate a class wrapper, but I don't really know how I could cleanly integrate those into my programming flow. 我已经研究了使用T4模板和CodeDOM自动生成代码以生成类包装器,但我真的不知道如何将它们干净地集成到我的编程流程中。

Ideally, I would like to be able to say on a top-level: 理想情况下,我希望能够在顶层说:

// Something like this?
using Int.UserId;

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

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

This kicks the code generation into gear at compile-time . 这使代码生成在编译时生成 If that's not possible or provides a chicken-and-egg issue for IntelliSense, an automatic compilation option that runs every x minutes (or a button or whatever) would be nice. 如果这不可能或者为IntelliSense提供鸡蛋问题,那么每x分钟(或按钮或其他)运行的自动编译选项会很好。

No, C# does not have such a feature. 不,C#没有这样的功能。 The closest you can get to this are structs. 你可以得到最接近的结构。

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

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

This way, the compiler indeed treats UserId and int as different types. 这样,编译器确实将UserIdint视为不同的类型。 Furthermore, you can add more methods to UserId that make sense given the fact that your int is effectively a user id. 此外,您可以向UserId添加更多有意义的方法,因为您的int实际上是用户ID。 Note as well that this does not have any effect on the runtime, using a struct with a single int field does not cause any overhead against using int directly. 还要注意,这对运行时没有任何影响,使用带有单个int字段的结构不会导致任何直接使用int开销。

Edit: Because you asked about T4, if you are working with Visual Studio, you can easily create a new T4 Text template that will expand to (C#)-code and will be compiled automatically. 编辑:因为您询问了T4,如果您正在使用Visual Studio,您可以轻松创建一个新的T4文本模板,该模板将扩展为(C#) - 代码并将自动编译。 The template will be executed everytime you save it. 每次保存时都会执行模板。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM