gpt4 book ai didi

c# - 删除 C# 中重复的、硬编码的循环和条件

转载 作者:太空狗 更新时间:2023-10-29 18:28:32 24 4
gpt4 key购买 nike

我有一个类比较相同对象的 2 个实例,并生成它们差异的列表。这是通过遍历键集合并用已更改内容的列表填充一组其他集合来完成的(在查看下面的代码后这可能更有意义)。这有效,并生成一个对象,让我知道在“旧”对象和"new"对象之间究竟添加和删除了什么。
我的问题/担忧是……它真的很难看,有很多循环和条件。有没有更好的方法来存储/处理这个,而不必如此严重地依赖于无休止的硬编码条件组?

    public void DiffSteps()
{
try
{
//Confirm that there are 2 populated objects to compare
if (NewStep.Id != Guid.Empty && SavedStep.Id != Guid.Empty)
{
//<TODO> Find a good way to compare quickly if the objects are exactly the same...hash?

//Compare the StepDoc collections:
OldDocs = SavedStep.StepDocs;
NewDocs = NewStep.StepDocs;
Collection<StepDoc> docstoDelete = new Collection<StepDoc>();

foreach (StepDoc oldDoc in OldDocs)
{
bool delete = false;
foreach (StepDoc newDoc in NewDocs)
{
if (newDoc.DocId == oldDoc.DocId)
{
delete = true;
}
}
if (delete)
docstoDelete.Add(oldDoc);
}

foreach (StepDoc doc in docstoDelete)
{
OldDocs.Remove(doc);
NewDocs.Remove(doc);
}


//Same loop(s) for StepUsers...omitted for brevity

//This is a collection of users to delete; it is the collection
//of users that has not changed. So, this collection also needs to be checked
//to see if the permisssions (or any other future properties) have changed.
foreach (StepUser user in userstoDelete)
{
//Compare the two
StepUser oldUser = null;
StepUser newUser = null;

foreach(StepUser oldie in OldUsers)
{
if (user.UserId == oldie.UserId)
oldUser = oldie;
}

foreach (StepUser newie in NewUsers)
{
if (user.UserId == newie.UserId)
newUser = newie;
}

if(oldUser != null && newUser != null)
{
if (oldUser.Role != newUser.Role)
UpdatedRoles.Add(newUser.Name, newUser.Role);
}

OldUsers.Remove(user);
NewUsers.Remove(user);
}

}
}
catch(Exception ex)
{
string errorMessage =
String.Format("Error generating diff between Step objects {0} and {1}", NewStep.Id, SavedStep.Id);
log.Error(errorMessage,ex);
throw;
}
}

目标框架是 3.5。

最佳答案

您使用的是 .NET 3.5 吗?我确信 LINQ to Objects 会让很多很多变得更简单。

另一件要考虑的事情是,如果你有很多具有共同模式的代码,其中只有少数事情发生了变化(例如“我正在比较哪个属性?”那么这是一个很好的通用方法的候选者代表这种差异的代表。

编辑:好的,现在我们知道我们可以使用 LINQ:

第 1 步:减少嵌套
首先,我会去掉一层嵌套。而不是:

if (NewStep.Id != Guid.Empty && SavedStep.Id != Guid.Empty)
{
// Body
}

我会:

if (NewStep.Id != Guid.Empty && SavedStep.Id != Guid.Empty)
{
return;
}
// Body

这样的早期返回可以使代码更具可读性。

第 2 步:查找要删除的文档

如果您可以简单地为 Enumerable.Intersect 指定一个键函数,那就更好了。您可以指定一个相等比较器,但构建其中一个比较器很痛苦,即使使用实用程序库也是如此。嗯。

var oldDocIds = OldDocs.Select(doc => doc.DocId);
var newDocIds = NewDocs.Select(doc => doc.DocId);
var deletedIds = oldDocIds.Intersect(newDocIds).ToDictionary(x => x);
var deletedDocs = oldDocIds.Where(doc => deletedIds.Contains(doc.DocId));

第 3 步:删除文档
使用现有的 foreach 循环,或更改属性。如果您的属性实际上是 List 类型,那么您可以使用 RemoveAll。

第 4 步:更新和删除用户

foreach (StepUser deleted in usersToDelete)
{
// Should use SingleOfDefault here if there should only be one
// matching entry in each of NewUsers/OldUsers. The
// code below matches your existing loop.
StepUser oldUser = OldUsers.LastOrDefault(u => u.UserId == deleted.UserId);
StepUser newUser = NewUsers.LastOrDefault(u => u.UserId == deleted.UserId);

// Existing code here using oldUser and newUser
}

进一步简化事情的一种选择是使用 UserId 实现 IEqualityComparer(还有一个用于带有 DocId 的文档)。

关于c# - 删除 C# 中重复的、硬编码的循环和条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/210353/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com