Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在集合c中查找循环依赖项#_C#_.net - Fatal编程技术网

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");        
}