首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何正确使用以类为键的TryGetValue方法?

如何正确使用以类为键的TryGetValue方法?
EN

Stack Overflow用户
提问于 2022-01-09 13:50:14
回答 2查看 624关注 0票数 0

我的问题是关于字典的使用。我将尝试附上密码,然后解释我的怀疑:

代码语言:javascript
复制
    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);
    }

我的怀疑与我使用

代码语言:javascript
复制
ambassadors.TryGetValue

方法在if中检查密钥并将值还给我。我的问题是:为什么要在CountrySide中创建类TryGetValue的新实例(或初始化)?

我的意思是这个类的一个例子已经存在于大使字典中。那么,为什么c#要求我在TryGetValue方法中初始化一个新的方法,而不是简单地检查这个特定的方法是否存在,而没有CoutryCode(代码)之前的“新”?

如果你能澄清我这个概念,我会非常感激的。

EN

回答 2

Stack Overflow用户

发布于 2022-01-09 14:06:05

您不需要CountryCode类,字符串类型就足够了

代码语言:javascript
复制
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)方法。

代码语言:javascript
复制
var ambassadors = new Dictionary<string, Ambassador>();

您可以以这种方式将项添加到字典中。

代码语言:javascript
复制
    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);

所有其他代码都将与我上面发布的代码相同。

票数 0
EN

Stack Overflow用户

发布于 2022-01-09 15:10:58

其他的答案和注释已经阐述过了:您的字典由CountryCode键控,因此需要一个CountryCode实例,因此需要在

代码语言:javascript
复制
ambassadors.TryGetValue(new CountryCode(code), out var ambassador)

我想在这里评论一个不同的角度:当您可以使字典按string键,然后使用

代码语言:javascript
复制
var ambassadors = new Dictionary<string, Ambassador>(StringComparer.OrdinalIgnoreCase);
// ...
ambassadors.TryGetValue(code, out var ambassador)

直接地,它需要泄漏国家代码是如何比较的知识-注意StringComparer.OrdinalIgnoreCase在那里。

我认为将CountryCode改为struct可能有好处:

代码语言:javascript
复制
public readonly struct CountryCode
{
    public string Code { get; }
    // ...
}

这将保留所有验证代码--即类型构造函数仍然可以检查某些内容是否是有效的国家代码,而不是空的或空白等等--但是它将节省分配的资源:由于struct是值类型,所以new在堆栈上而不是堆上分配,因此就您在这里的使用而言,它实际上是免费的。

关键的部分--你已经有了--是设置了EqualsGetHashCode。如前所述,Equals在这里非常重要,因为它允许将engENG视为相似的。考虑到这一点,CountryCode键控的任何类型都不需要知道或关心将两个国家代码等同的细节,这比string密钥有很大的好处。

为了可用性,我建议还实现IEquatable<CountryCode>接口,以及operator ==operator !=重载:

代码语言:javascript
复制
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);
}

如果您处理的是常见名称,那么我成功地将构造函数设置为私有,并将值命名如下:

代码语言:javascript
复制
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转换运算符:

代码语言:javascript
复制
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 242
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70641928

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档