C#有符号类型吗?

6

JavaScript (ES2015) 引入了新的 Symbol 类型,与字符串不同的是,符号是按引用比较的,而字符串是按值比较的。

C# 有类似的东西吗?


3
string和Symbol的区别稍微深入一些,Symbol是一种我们无法获取值的东西。在C#中,这可以是任何类,因为类实例是按引用比较的。 - Grundy
有趣的想法...将类作为符号。谢谢你的建议 :-) - Golo Roden
2
没有dv。但是Object.ReferenceEquals呢? - Willem Van Onsem
1
以下代码输出 True(value)/False(reference)string s1 = new String(new [] {'f','o', 'o'}); string s2 = new String(new [] {'f','o', 'o'}); Console.WriteLine(s1.Equals(s2)); Console.WriteLine(Object.ReferenceEquals(s1, s2)); @CommuSoft 比我更快地发表了评论。 - keenthinker
这在C#中是不必要的,因为它既有Guid(用于持久标识),也有object.ReferenceEquals()(用于短暂标识)。 - Matthew Watson
1个回答

8

C#中的object与ECMAScript 6中的symbol具有许多相似的属性。

考虑以下JavaScript代码:

const MY_KEY = Symbol();
let obj = {};

obj[MY_KEY] = 123;
console.log(obj[MY_KEY]); // 123

在C#中,这可以类似地表示为:
readonly object MyKey = new object();
// ...
var obj = new Dictionary<object, int>() {{MyKey, 123}};
Console.WriteLine(obj[MyKey]); // 123

然而,Symbol 类型包括额外的功能:全局注册表、众所周知的键和用描述标记符号的功能(ES2015 规范,§19.4)。在 C# 6 中,可以通过简单的包装器大部分地复制此功能:

class Symbol : IEquatable<Symbol>
{
    private object o = new object();
    public string Description { get; }

    public Symbol(string description)
    {
        Description = description;
    }
    public Symbol() : this(null) { }

    public bool Equals(Symbol other) => other?.o == o;
    public static bool operator == (Symbol o1, Symbol o2) => 
        EqualityComparer<Symbol>.Default.Equals(o1, o2);
    public static bool operator !=(Symbol o1, Symbol o2) => !(o1 == o2);

    public override int GetHashCode()
    {
        return o.GetHashCode();
    }
    public override bool Equals(object obj)
    {
        return Equals(obj as Symbol);
    }
    public override string ToString() => $"symbol({Description})";

    // static methods to support symbol registry
    private static Dictionary<string, Symbol> GlobalSymbols = 
          new Dictionary<string, Symbol>(StringComparer.Ordinal);

    public static Symbol For(string key) => 
          GlobalSymbols.ContainsKey(key) ? 
                GlobalSymbols[key] :
                GlobalSymbols[key] = new Symbol(key);

    public static string KeyFor(Symbol s) =>
          GlobalSymbols.FirstOrDefault(a => a.Value == s).Key; // returns null if s not defined

    // Well-known ECMAScript symbols
    private const string ns = "Symbol.";
    public static Symbol HasInstance => For(ns + "hasInstance");
    public static Symbol IsConcatSpreadable => For(ns + "isConcatSpreadable");
    public static Symbol Iterator => For(ns + "iterator");
    public static Symbol Match => For(ns + "match");
    public static Symbol Replace => For(ns + "replace");
    public static Symbol Search => For(ns + "search");
    public static Symbol Species => For(ns + "species");
    public static Symbol Split => For(ns + "split");
    public static Symbol ToPrimitive => For(ns + "toPrimitive");
    public static Symbol ToStringTag => For(ns + "toStringTag");
    public static Symbol Unscopables => For(ns + "unscopables");
}

以下行为符合预期的ECMAScript行为:

Symbol a = new Symbol();
Symbol b = new Symbol("A");
Symbol c = new Symbol("A");
Symbol d = c;
var dict = new Dictionary<object, int>() { { c, 42 } };
Symbol e = Symbol.For("X");
Symbol f = Symbol.For("X");
Symbol g = Symbol.For("Y");
Console.WriteLine(a == b); // false
Console.WriteLine(b == c); // false
Console.WriteLine(c == d); // true
Console.WriteLine(dict[d]); // 42
Console.WriteLine(e == f); // true
Console.WriteLine(f == g); // false
Console.WriteLine(Symbol.For("X") == e); // true
Console.WriteLine(Symbol.KeyFor(e) == "X"); // true
Console.WriteLine(Symbol.Unscopables.Description); // Symbol.unscopables

没有必要创建自定义类型;你已经可以通过引用或值比较任何string对象了。 - Servy
1
@Servy 按值比较字符串并不相同。ECMAScript符号对象支持创建具有自定义描述的不透明标记,并提供诸如全局注册表之类的补充功能。这些属性不能通过字符串引用比较来满足。 - drf
简而言之:不,C#没有符号类型,但你可以轻松地自己创建一个。 - Golo Roden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接