C# 在集合c中查找循环依赖项#
我有一个C# 在集合c中查找循环依赖项#,c#,.net,C#,.net,我有一个DataItem类的集合 数据项:属性RefItem存储对可能是同一集合的数据项的引用 public class DataItem { public int ID { get; set; } public string Name { get; set; } public DataItem RefItem { get; set; } } public void AddItem(DataItem item) { DataItems.Add(
DataItem
类的集合
数据项:属性
RefItem
存储对可能是同一集合的数据项的引用
public class DataItem
{
public int ID { get; set; }
public string Name { get; set; }
public DataItem RefItem { get; set; }
}
public void AddItem(DataItem item)
{
DataItems.Add(item);
}
public bool ValidateDataItems()
{
//Logic for circular reference
//
return true;
}
收藏:
private List<DataItem> dataitems;
public List<DataItem> DataItems
{
get { return dataitems; }
set { dataitems = value; }
}
我想在validate方法中使用一个算法来检查我的集合中是否存在任何循环依赖项。例如,下面的数据对我来说是无效的。项目1再次指出了项目3
var item1 = new DataItem() {ID=1,Name="First Item",RefItem =null};
var item2 = new DataItem() { ID = 1, Name = "First Item", RefItem = item1 };
var item3 = new DataItem() { ID = 1, Name = "First Item", RefItem = item2 };
item1.RefItem = item3;
AddItem(item1);
AddItem(item2);
AddItem(item3);
如果将项添加到集合中,如Item1->item2、item2->item3、item3->Item1或类的ref项指向后面的任何其他可能组合。我希望验证方法返回false
这是一个循环依赖问题,但我在c#中找不到任何具体的算法 试试这样的方法:
公共类数据项
{
公共int ID{get;set;}
公共字符串名称{get;set;}
公共数据项{get;set;}
}
公共类检查器
{
公共静态布尔检查(数据项)
{
var chain=新字典();
添加(项目,空);
尝试
{
ProcessNodes(链、项);
返回true;
}
捕获(异常)
{
返回false;
}
}
私有静态void ProcessNodes(字典链、数据项)
{
如果(item.RefItem!=null)
{
chain.Add(item.em,空);
ProcessNodes(链、item.RefItem);
}
}
公共静态bool ValidateDataItems(列表项)
{
foreach(项目中的var项目)
如果(!检查(项目))
返回false;
返回true;
}
}
公共静态void Main()
{
var item1=new DataItem(){ID=1,Name=“First Item”,RefItem=null};
var item2=new DataItem(){ID=1,Name=“First Item”,RefItem=item1};
var item3=new DataItem(){ID=1,Name=“First Item”,RefItem=item2};
项目1.em=项目3;
控制台写入线(检查者检查(第1项));
item1.em=null;
控制台写入线(检查者检查(第1项));
//示例如何检查所有现有项目
Console.WriteLine(Checker.ValidateDataItems(新列表{item1,item2,item3})-“项目正常”:“一个或多个项目具有依赖关系”);
}
尝试以下方法:
公共类数据项
{
公共int ID{get;set;}
公共字符串名称{get;set;}
公共数据项{get;set;}
}
公共类检查器
{
公共静态布尔检查(数据项)
{
var chain=新字典();
添加(项目,空);
尝试
{
ProcessNodes(链、项);
返回true;
}
捕获(异常)
{
返回false;
}
}
私有静态void ProcessNodes(字典链、数据项)
{
如果(item.RefItem!=null)
{
chain.Add(item.em,空);
ProcessNodes(链、item.RefItem);
}
}
公共静态bool ValidateDataItems(列表项)
{
foreach(项目中的var项目)
如果(!检查(项目))
返回false;
返回true;
}
}
公共静态void Main()
{
var item1=new DataItem(){ID=1,Name=“First Item”,RefItem=null};
var item2=new DataItem(){ID=1,Name=“First Item”,RefItem=item1};
var item3=new DataItem(){ID=1,Name=“First Item”,RefItem=item2};
项目1.em=项目3;
控制台写入线(检查者检查(第1项));
item1.em=null;
控制台写入线(检查者检查(第1项));
//示例如何检查所有现有项目
Console.WriteLine(Checker.ValidateDataItems(新列表{item1,item2,item3})-“项目正常”:“一个或多个项目具有依赖关系”);
}
谢谢您的回答。但我不能限制用户在集合中添加项目,如果发生上述情况,我只需显示一些验证消息。假设它已经有了一个集合,现在我只需要验证它。另外,如果列表中的项目没有通过ref连接,那么我必须再次调用Check方法。既然我不能在编译时做出这个决定,我就必须为每一项调用它。@KyloRen然后,不要抛出异常,而是显示验证消息。通常最好不要损坏集合,然后在事后花时间检查它。回答第一条评论:当你向集合添加新项目时,不要检查它。然后,您可以遍历整个列表,并检查递归依赖项和第一个存在项上的每个项返回true
,否则返回false
。你可以在任何时候表演。我不完全理解第二条评论:你问如果其中一个依赖项不是通过引用传递的,而是作为项的副本传递的,你能更清楚地解释一下吗?@SlavaUtesinov第二条评论的意思是,你的逻辑使用RefItem属性在项中进一步导航,但不能确定是否所有项都已处理,因为有些值可以为空。谢谢你的回答。但我不能限制用户在集合中添加项目,如果发生上述情况,我只需显示一些验证消息。假设它已经有了一个集合,现在我只需要验证它。另外,如果列表中的项目没有通过ref连接,那么我必须再次调用Check方法。既然我不能在编译时做出这个决定,我就必须为每一项调用它。@KyloRen然后,不要抛出异常,而是显示验证消息。通常最好不要损坏集合,然后在事后花时间检查它。回答第一条评论:当你向集合添加新项目时,不要检查它。然后,您可以遍历整个列表,并检查递归依赖项和第一个存在项上的每个项返回true
,否则返回false
。你可以按
public class DataItem
{
public int ID { get; set; }
public string Name { get; set; }
public DataItem RefItem { get; set; }
}
public class Checker
{
public static bool Check(DataItem item)
{
var chain = new Dictionary<DataItem, DataItem>();
chain.Add(item, null);
try
{
ProcessNodes(chain, item);
return true;
}
catch (ArgumentException)
{
return false;
}
}
private static void ProcessNodes(Dictionary<DataItem, DataItem> chain, DataItem item)
{
if (item.RefItem != null)
{
chain.Add(item.RefItem, null);
ProcessNodes(chain, item.RefItem);
}
}
public static bool ValidateDataItems(List<DataItem> items)
{
foreach(var item in items)
if(!Check(item))
return false;
return true;
}
}
public static void Main()
{
var item1 = new DataItem() { ID = 1, Name = "First Item", RefItem = null };
var item2 = new DataItem() { ID = 1, Name = "First Item", RefItem = item1 };
var item3 = new DataItem() { ID = 1, Name = "First Item", RefItem = item2 };
item1.RefItem = item3;
Console.WriteLine(Checker.Check(item1));
item1.RefItem = null;
Console.WriteLine(Checker.Check(item1));
//Sample how to check all existing items
Console.WriteLine(Checker.ValidateDataItems(new List<DataItem>{item1, item2, item3}) ? "items is OK" : "One or more items have dependency");
}