我正在尝试根据内部字典的键访问和分配值,该字典恰好是一个自定义对象PlanTier,它具有2个属性PlanName和Tiers。
问题从这里开始: curEnrollByEnrolledOrWaived [group.Key] [waivedPlanTier] = enrByGroupAndPlan [group.Key] [waivedPlanTier];
请注意,虽然预先填充了字典“ curEnrollByEnrolledOrWaived”和“ enrByGroupAndPlan”(作为输入参数),但PlanTier对象“ waivedPlanTier”(我正试图使用(作为键)在这些字典中查找相应的值)是在此函数中初始化。
我已阅读到该问题是由对象引用引起的,因此这两个词典中确实包含与“ waivedPlanTier”具有相同属性的键。另一件事,
问题: 是否可以通过将内部字典的键与“ waivedPlanTier”等同来获取内部字典的相应值?如果是这样,我该怎么办?
如果不可能,是否还有其他方法可以使用“ waivedPlanTier”基于键访问和分配值?
代码如下:
private static Dictionary<string, Dictionary<PlanTier, double>> PopulateEnrollOrWaived(Dictionary<string, Dictionary<PlanTier, double>> fullListByGroupAndEnrStatus, Dictionary<string, Dictionary<PlanTier, double>> enrByGroupAndPlan, List<string> distinctTierList) (Dictionary<string, Dictionary<PlanTier, double>> fullListByGroupAndEnrStatus
, Dictionary<string, Dictionary<PlanTier, double>> enrByGroupAndPlan
, List<string> distinctTierList)
{
Dictionary<string, Dictionary<PlanTier, double>> curEnrollByEnrolledOrWaived =
fullListByGroupAndEnrStatus.ToDictionary(x => x.Key, x => x.Value.ToDictionary(y => y.Key, y => y.Value));
PlanTierComparer comparer = new PlanTierComparer();
foreach (var group in curEnrollByEnrolledOrWaived)
{
foreach (var tier in distinctTierList)
{
if (enrByGroupAndPlan.ContainsKey(group.Key))
{
PlanTier waivedPlanTier = new PlanTier(Enums.Literals.WaivedPlanName, tier);
PlanTier enrolledPlanTier = new PlanTier("Enrolled", tier);
var test = curEnrollByEnrolledOrWaived[group.Key];
var test1 = test.Keys.Where(x => x.Equals(waivedPlanTier));
curEnrollByEnrolledOrWaived[group.Key][waivedPlanTier] =
enrByGroupAndPlan[group.Key][waivedPlanTier];
curEnrollByEnrolledOrWaived[group.Key][enrolledPlanTier] =
enrByGroupAndPlan[group.Key].Values.Sum()
- curEnrollByEnrolledOrWaived[group.Key][waivedPlanTier];
}
}
}
return curEnrollByEnrolledOrWaived;
}
答案 0 :(得分:0)
默认情况下,按引用检查引用类型是否相等:new PlanTier("plan2", "tier1").Equals(new PlanTier("plan2", "tier1"))
始终为false。因此,如果您将引用类型用作字典键,则查找也将通过引用进行。
当您需要按值查找时,基本上有两个选择:
像这样执行IEqualityComparer<T>:
class PlanTierComparer : IEqualityComparer<PlanTier>
{
public static readonly PlanTierComparer Instance = new PlanTierComparer();
PlanTierComparer() { }
public bool Equals(PlanTier x, PlanTier y)
{
if (x == null && y == null)
return true;
if (x == null || y == null)
return false;
return x.PlanName == y.PlanName && x.Tiers == y.Tiers;
}
public int GetHashCode(PlanTier obj)
{
return obj != null ? obj.PlanName.GetHashCode() ^ obj.Tiers.GetHashCode() : 0;
}
}
(我假设 PlanName 和 Tiers 属性不能为空。)
并使用此比较器创建字典:
var pt1 = new PlanTier("plan1", "tier1");
var pt2 = new PlanTier("plan1", "tier2");
var pt3 = new PlanTier("plan2", "tier1");
// Dictionary ctor example
var dic1 = new Dictionary<PlanTier, double>(PlanTierComparer.Instance) { { pt1, 1.0 }, { pt2, 2.0 }, { pt3, 3.0 } };
// ToDictionary() example
var dic2 = new[]
{
new KeyValuePair<PlanTier, double>(pt1, 1.0),
new KeyValuePair<PlanTier, double>(pt2, 2.0),
new KeyValuePair<PlanTier, double>(pt3, 3.0),
}.ToDictionary(p => p.Key, p => p.Value, PlanTierComparer.Instance);
或者仅使您的键类型实现IEquatable<T>:
class PlanTier : IEquatable<PlanTier>
{
public PlanTier(string planName, string tiers)
{
PlanName = planName ?? throw new ArgumentNullException(nameof(planName));
Tiers = tiers ?? throw new ArgumentNullException(nameof(tiers));
}
public string PlanName { get; }
public string Tiers { get; }
public override bool Equals(object obj)
{
return obj is PlanTier other ? Equals(other) : false;
}
public override int GetHashCode()
{
return PlanName.GetHashCode() ^ Tiers.GetHashCode();
}
public bool Equals(PlanTier other)
{
if (other == null)
return false;
return PlanName == other.PlanName && Tiers == other.Tiers;
}
}
您还需要重写 GetHashCode 和 Equals(object)方法,以使其正常工作。 (实际上,您可以仅重写这两种方法,而不必实现 IEquatable
使用复杂类型作为字典键时要记住的另一件事:键对象应该是不可变!换句话说,键对象的状态在创建后不应更改,因为这可能导致哈希码发生更改,从而破坏字典的功能。