JavaScript (ES2015) 引入了新的 Symbol
类型,与字符串不同的是,符号是按引用比较的,而字符串是按值比较的。
C# 有类似的东西吗?
C#
中的object
与ECMAScript 6中的symbol
具有许多相似的属性。
考虑以下JavaScript代码:
const MY_KEY = Symbol();
let obj = {};
obj[MY_KEY] = 123;
console.log(obj[MY_KEY]); // 123
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
Object.ReferenceEquals
呢? - Willem Van OnsemTrue(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 比我更快地发表了评论。 - keenthinkerGuid
(用于持久标识),也有object.ReferenceEquals()
(用于短暂标识)。 - Matthew Watson