admin管理员组

文章数量:1410730

JavaScript (ES2015) introduces the new Symbol type, which differs from strings in that symbols are pared by reference, while strings are pared by value.

Does C# have anything parable?

JavaScript (ES2015) introduces the new Symbol type, which differs from strings in that symbols are pared by reference, while strings are pared by value.

Does C# have anything parable?

Share Improve this question asked Dec 19, 2015 at 13:24 Golo RodenGolo Roden 151k102 gold badges315 silver badges444 bronze badges 5
  • 3 difference between string and Symbol a bit deeper, symbol is a something where we can't get value. And in C# this can be any class, because class instance pared by reference – Grundy Commented Dec 19, 2015 at 13:32
  • Interesting thought … classes as symbols. Thanks for the idea :-) – Golo Roden Commented Dec 19, 2015 at 13:33
  • 2 didn't dv. But what about Object.ReferenceEquals? – willeM_ Van Onsem Commented Dec 19, 2015 at 13:33
  • 1 The following 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)); outputs True(value)/False(reference). @CommuSoft was faster with the ment than me. – keenthinker Commented Dec 19, 2015 at 13:39
  • This is not necessary in C# which has both Guid (for persistent identity) and object.ReferenceEquals() (for ephemeral identity). – Matthew Watson Commented Dec 19, 2015 at 15:16
Add a ment  | 

1 Answer 1

Reset to default 8

object in C# satisfies many of the same properties of symbol in ECMAScript 6.

Consider the JavaScript code:

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

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

In C#, this can be similarly represented as:

readonly object MyKey = new object();
// ...
var obj = new Dictionary<object, int>() {{MyKey, 123}};
Console.WriteLine(obj[MyKey]); // 123

However, the Symbol type enpasses additional functionality: a global registry, well-known keys, and the functionality to tag symbols with descriptions (ES2015 specification, § 19.4). This functionality can be largely reproduced in C# 6 as a simple wrapper:

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");
}

The resulting behavior is in line with the expected ECMAScript behavior:

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

本文标签: javascriptDoes C have a symbol typeStack Overflow