代码之家  ›  专栏  ›  技术社区  ›  James Dunne

有没有办法定义现有基本类型(如'string'或'int')的C强类型别名?

  •  17
  • James Dunne  · 技术社区  · 16 年前

    也许我是在证明我对C#或.NET framework的一些常用功能一无所知,但我想知道是否有一种本机支持的方法来创建类似的类型别名 EmailAddress string 但是我可以用我自己的方法来扩展它,比如 bool Validate() ?

    我知道 using x = Some.Type; 别名,但这些别名不是全局的,也不提供类型安全性,即可以替换普通别名 一串 电子邮件地址 为其自身类型,独立且不可与 键入它的阴影。

    public sealed partial EmailAddress : IEquatable<EmailAddress>, IXmlSerializable 使用T4模板生成样板隐式字符串转换运算符和其他类似内容的类。目前,这对我来说还不错,给了我很大的灵活性,但在我的脑海深处,我不得不生成大量的样板代码来做一些简单的事情,比如创建一个强类型别名,这似乎很愚蠢。

    也许除了代码生成之外,这是不可能的,但我很好奇是否有其他人尝试过类似的设计,以及您的经历。如果没有其他东西的话,也许这可以作为C#未来假设版本中此类别名功能的一个很好的用例。谢谢

    编辑:我想从中得到的真正价值是能够通过表示不同数据类型/格式的基本类型获得类型安全性。例如,一个 和 SocialSecurityNumber PhoneNumber 一串

    7 回复  |  直到 16 年前
        1
  •  5
  •   Doug Ferguson    16 年前

    如果您看一下.NET Framework System.Uri,它是与电子邮件地址类似的最接近的示例。在.NET中,模式是将某些内容包装在类中并以这种方式添加约束。

    为简单类型添加附加约束的强类型是一个有趣的语言特性,我相信某些函数式语言已经具备了这一特性。我想不起语言的名称,它可以让你在你的值中添加维度单位,如英尺,并对你的方程进行维度分析,以确保这些单位匹配。

        2
  •  4
  •   Igor Zevaka    16 年前

    关于原因的一些背景资料 string

    从…起 http://www.code-magazine.com/Article.aspx?quickid=0501091

    嘿,杰,你介意我问你一个问题吗 几个问题?我已经很好奇了 关于一些事情。首先,以及 这是在一个MSDN上提出来的 密封的?注:对于VB.NET程序员, Sealed=不可继承。

    杰伊:因为我们有很多魔术 我们可以针对以下方面进行优化 我们可能会。那么,我们在偷东西 在那里做标记。只是为了 举个例子,我不知道 这是我开始的时候,但是如果一个字符串 里面有连字符或撇号 里面只有文本,还有算法 如果有连字符或 很复杂,所以我们实际上标记了 不管字符串是否具有该属性 其中的行为类型。

    在弦乐世界里,如果你没有 如果 人们试图对它进行分类。

    对象的整个布局,所以我们 我们玩得很快。

    以下是您以前可能看过的CodeProject文章:

    http://www.codeproject.com/KB/cs/expandSealed.aspx

        3
  •  2
  •   JMD    16 年前

    是吗 System.Net.Mail.MailAddress

    编辑:它不是显式的IEquatable或ISerializable,但是您可以很容易地将它们添加到您自己的包装器中。

        4
  •  2
  •   Andre Pena    16 年前

    看起来你至少有一个合理的C#knoledgde,所以我的答案可能看起来很愚蠢,但你想要的是所谓的“类型层次结构”,编写String类的人想阻止你使用这个“OO特性”,所以他们将String类密封起来,这就是为什么你不能做你想做的事情。现在最好的方法是:创建自己的类型并隐式转换为字符串。

        5
  •  1
  •   AKCoder    16 年前

    我想你应该使用扩展方法。它们允许您在不创建新的派生类型的情况下扩展类功能。

        6
  •  1
  •   devio    16 年前

    我想我不明白为什么要同时进行强类型和隐式字符串转换。对我来说,一个排除了另一个。

    我试图为int解决同样的问题(你在标题中提到int,但在问题中没有提到)。我发现声明枚举会给您一个类型安全的整数,需要显式地从/转换为int。

    更新

    预定的 对于开放集,但仍然可以

        enum ProcID { Unassigned = 0 }
        enum TenderID { Unassigned = 0 }
    
        void Test()
        {
            ProcID p = 0;
            TenderID t = 0; <-- 0 is assignable to every enum
            p = (ProcID)3;  <-- need to explicitly convert
    
            if (p == t)  <-- operator == cannot be applied
                t = -1;  <-- cannot implicitly convert
    
            DoProc(p);
            DoProc(t);   <-- no overloaded method found
            DoTender(t);
        }
    
        void DoProc(ProcID p)
        {
        }
    
        void DoTender(TenderID t)
        {
        }
    
        7
  •  0
  •   BernardV    10 年前

    我上这门课是为了满足同样的需要。这一个用于类型“int”(我还有一个用于“string”):

    public class NamedInt : IComparable<int>, IEquatable<int>
    {
        internal int Value { get; }
    
        protected NamedInt() { }
        protected NamedInt(int val) { Value = val; }
        protected NamedInt(string val) { Value = Convert.ToInt32(val); }
    
        public static implicit operator int (NamedInt val) { return val.Value; }
    
        public static bool operator ==(NamedInt a, int b) { return a?.Value == b; }
        public static bool operator ==(NamedInt a, NamedInt b) { return a?.Value == b?.Value; }
        public static bool operator !=(NamedInt a, int b) { return !(a==b); }
        public static bool operator !=(NamedInt a, NamedInt b) { return !(a==b); }
    
        public bool Equals(int other) { return Equals(new NamedInt(other)); }
        public override bool Equals(object other) {
            if ((other.GetType() != GetType() && other.GetType() != typeof(string))) return false;
            return Equals(new NamedInt(other.ToString()));
        }
        private bool Equals(NamedInt other) {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return Equals(Value, other.Value);
        }
    
        public int CompareTo(int other) { return Value - other; }
        public int CompareTo(NamedInt other) { return Value - other.Value; }
    
        public override int GetHashCode() { return Value.GetHashCode(); }
    
        public override string ToString() { return Value.ToString(); }
    }
    

    在您的案例中使用它:

    public class MyStronglyTypedInt: NamedInt {
        public MyStronglyTypedInt(int value) : base(value) {
            // Your validation can go here
        }
        public static implicit operator MyStronglyTypedInt(int value) { 
            return new MyStronglyTypedInt(value);
        }
    
        public bool Validate() {
            // Your validation can go here
        }
    }