我的问题是关于字典的使用。我将尝试附上密码,然后解释我的怀疑:
var ambassadors = new Dictionary<CountryCode, Ambassador>();
Ambassador england = new Ambassador
{
CountryCode = new CountryCode("eng"),
Name = "John",
Age = 25
};
Ambassador australia = new Ambassador
{
CountryCode = new CountryCode("aus"),
Name = "Martin",
Age = 49
};
ambassadors.Add(england.CountryCode, england);
ambassadors.Add(australia.CountryCode, australia);
Console.WriteLine("Enter country code: ");
var code = Console.ReadLine();
if (ambassadors.TryGetValue(new CountryCode(code), out Ambassador ambassador))
{
Console.WriteLine($"The ambassador is {ambassador.Name}");
}
else
{
Console.WriteLine("The ambassador with the given code does not exist in the dictonary");
}
Console.ReadLine();
}
public class Ambassador
{
public CountryCode CountryCode { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
public class CountryCode
{
public string Code { get; }
public CountryCode(string code)
{
Code = code;
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (!(obj is CountryCode))
{
return false;
}
return StringComparer.OrdinalIgnoreCase.Equals(this.Code, ((CountryCode)obj).Code);
}
public override int GetHashCode()
{
return StringComparer.OrdinalIgnoreCase.GetHashCode(this.Code);
}我的怀疑与我使用
ambassadors.TryGetValue方法在if中检查密钥并将值还给我。我的问题是:为什么要在CountrySide中创建类TryGetValue的新实例(或初始化)?
我的意思是这个类的一个例子已经存在于大使字典中。那么,为什么c#要求我在TryGetValue方法中初始化一个新的方法,而不是简单地检查这个特定的方法是否存在,而没有CoutryCode(代码)之前的“新”?
如果你能澄清我这个概念,我会非常感激的。
发布于 2022-01-09 14:06:05
您不需要CountryCode类,字符串类型就足够了
var ambassadors = new Dictionary<string, Ambassador>();
public class Ambassador
{
public string CountryCode { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
....
Ambassador england = new Ambassador
{
CountryCode = "eng",
Name = "John",
Age = 25
};
if ( ambassadors.TryGetValue(code, out var ambassador))
{
Console.WriteLine($"The ambassador is {ambassador.Name}");
}
else
{
Console.WriteLine($"The ambassador with the given code \"{code}\" does not exist in the dictonary");
}
// or you can use this too
if (ambassadors.ContainsKey(code))
{
Console.WriteLine($"The ambassador is {ambassadors[code].Name}");
}
else
{
Console.WriteLine($"The ambassador with the given code \"{code}\" does not exist in the dictonary");
}如果出于某些原因,需要使用CountryCode类,则最好以这种方式定义字典。在这种情况下,您可能不需要CountryCode类的bool (Object)方法。
var ambassadors = new Dictionary<string, Ambassador>();您可以以这种方式将项添加到字典中。
Ambassador england = new Ambassador
{
CountryCode = new CountryCode("eng"),
Name = "John",
Age = 25
};
Ambassador australia = new Ambassador
{
CountryCode = new CountryCode("aus"),
Name = "Martin",
Age = 49
};
ambassadors.Add(england.CountryCode.Code, england);
ambassadors.Add(australia.CountryCode.Code, australia);所有其他代码都将与我上面发布的代码相同。
发布于 2022-01-09 15:10:58
其他的答案和注释已经阐述过了:您的字典由CountryCode键控,因此需要一个CountryCode实例,因此需要在
ambassadors.TryGetValue(new CountryCode(code), out var ambassador)我想在这里评论一个不同的角度:当您可以使字典按string键,然后使用
var ambassadors = new Dictionary<string, Ambassador>(StringComparer.OrdinalIgnoreCase);
// ...
ambassadors.TryGetValue(code, out var ambassador)直接地,它需要泄漏国家代码是如何比较的知识-注意StringComparer.OrdinalIgnoreCase在那里。
我认为将CountryCode改为struct可能有好处:
public readonly struct CountryCode
{
public string Code { get; }
// ...
}这将保留所有验证代码--即类型构造函数仍然可以检查某些内容是否是有效的国家代码,而不是空的或空白等等--但是它将节省分配的资源:由于struct是值类型,所以new在堆栈上而不是堆上分配,因此就您在这里的使用而言,它实际上是免费的。
关键的部分--你已经有了--是设置了Equals和GetHashCode。如前所述,Equals在这里非常重要,因为它允许将eng和ENG视为相似的。考虑到这一点,CountryCode键控的任何类型都不需要知道或关心将两个国家代码等同的细节,这比string密钥有很大的好处。
为了可用性,我建议还实现IEquatable<CountryCode>接口,以及operator ==和operator !=重载:
public readonly struct CountryCode : IEquatable<CountryCode>
{
// Note: `default(CountryCode)` will not call the constructor!
private readonly string? _code;
public CountryCode(string code)
{
// Verify country codes, throw exceptions, ...
_code = code?.Trim().ToLowerInvariant() ?? throw new ArgumentNullException(nameof(code));
}
// Note: ensure proper values for `default(CountryCode)`.
public string Code => _code ?? string.Empty;
public bool Equals(CountryCode other) =>
StringComparer.OrdinalIgnoreCase.Equals(Code, other);
public override bool Equals(object? obj) =>
obj is CountryCode other && Equals(other);
public override int GetHashCode() =>
StringComparer.OrdinalIgnoreCase.GetHashCode(Code);
public static bool operator ==(CountryCode lhs, CountryCode rhs) =>
lhs.Equals(rhs);
public static bool operator !=(CountryCode lhs, CountryCode rhs) =>
!lhs.Equals(rhs);
}如果您处理的是常见名称,那么我成功地将构造函数设置为私有,并将值命名如下:
public readonly struct CountryCode : IEquatable<CountryCode>
{
public static readonly CountryCode Empty = default;
public static readonly CountryCode England = new("eng");
public static readonly CountryCode Australia = new("aus");
// ...
}大多数反序列化代码仍将获取私有构造函数,但任何应用程序代码都将被迫使用允许的值。这对你的情况可能有用,也可能没有用。
注意,还可以使用如下所示的string转换运算符:
public static implicit operator string(CountryCode code) =>
code.Code;但是,显式(var code = countryCode.Code)通常比隐式(var code = countryCode)更好,因此要谨慎对待它。
所以我的建议是:
CountryCode键,CountryCode成为readonly struct而不是class,这使得H 137监视default(CountryCode)实例,因为它们不会被调用构造函数;在class类型中,整个值将是D40。H 241f 242https://stackoverflow.com/questions/70641928
复制相似问题