C# 带有自定义比较器的复合

C# 带有自定义比较器的复合,c#,generics,C#,Generics,我在复合C#中实现自定义比较器时遇到问题。我想将自定义比较器传递给我的复合对象 这里是IComponent接口: namespace composite { public interface IComponent<T> { void Add(IComponent<T> component); IComponent<T> Find(T item); IComponent<T> Remov

我在复合C#中实现自定义比较器时遇到问题。我想将自定义比较器传递给我的复合对象

这里是IComponent接口:

namespace composite
{
    public interface IComponent<T>
    {
        void Add(IComponent<T> component);
        IComponent<T> Find(T item);
        IComponent<T> Remove(T item);
        string Display(int depth);
        string Name { get; set; }
    }
}
namespace composite
{
    using System;
    using System.Collections.Generic;

    public class Component<T> : IComponent<T>
    {
        public Component(string name)
        {
            this.Name = name;
        }

        public string Display(int depth)
        {
            return new string('-', depth) + this.Name + "\n";
        }

        public string Name { get; set; }

        public IComparer<T> MyComparer { get; private set; }

        //public IComparer<T> myComparer { set; }

        public void Add(IComponent<T> item)
        { 
            throw new NotImplementedException();
        }

        public IComponent<T> Find(T item)
        {

            //Here I want to use comparer object, instead of Equals
            //Something like this:

            //return MyComparer.Compare( ... ) == 0 ? this : null;

            return item.Equals(this.Name) ? this : null;
        }

        public IComponent<T> Remove(T item)
        {
            throw new NotImplementedException();
        }
    }
}
名称空间组合
{
公共接口IComponent
{
无效添加(IComponent组件);
i组件查找(T项);
i组件移除(T项);
字符串显示(整数深度);
字符串名称{get;set;}
}
}
对于复合对象的组件,我使用相同的接口

复合(我的组件集合)

名称空间组合
{
使用System.Collections.Generic;
使用System.Linq;
使用System.Runtime.CompilerServices;
使用系统文本;
公共类复合:IComponent
{
私有i收集组件;
私人i组件持有人;
公共组合(字符串名称)
{
this.Name=Name;
this.holder=null;
this.components=新列表();
}
公共字符串名称{get;set;}
公共无效添加(IComponent组件)
{
此.components.Add(组件);
}
公共IComponent查找(T项)
{
this.holder=this;
if(item.Equals(this.Name))
{
归还这个;
}
找到的IComponent=null;
//this.components.Select(s=>s.Name==item)
foreach(此.components中的IComponent组件)
{
查找=组件。查找(项目);
如果(找到!=null)
{
打破
}
}
发现退货;
}
公共IComponent删除(T项)
{
this.holder=this;
IComponent p=持有者。查找(项目);
if(this.holder!=null)
{
(此支架为复合材料)。部件。移除(p);
将本文件退还给持有人;
}
其他的
{
归还这个;
}
}
//公共IEnumerable Dsiplay(整数深度)
公共字符串显示(整数深度)
{
StringBuilder s=新的StringBuilder();
s、 追加(“set”+this.Name+”长度:“+this.components.Count+”\n”);
foreach(组件中的IComponent组件)
{
s、 追加(组件显示(深度+2));
}
返回s.ToString();
}
}
}
组件:

namespace composite
{
    public interface IComponent<T>
    {
        void Add(IComponent<T> component);
        IComponent<T> Find(T item);
        IComponent<T> Remove(T item);
        string Display(int depth);
        string Name { get; set; }
    }
}
namespace composite
{
    using System;
    using System.Collections.Generic;

    public class Component<T> : IComponent<T>
    {
        public Component(string name)
        {
            this.Name = name;
        }

        public string Display(int depth)
        {
            return new string('-', depth) + this.Name + "\n";
        }

        public string Name { get; set; }

        public IComparer<T> MyComparer { get; private set; }

        //public IComparer<T> myComparer { set; }

        public void Add(IComponent<T> item)
        { 
            throw new NotImplementedException();
        }

        public IComponent<T> Find(T item)
        {

            //Here I want to use comparer object, instead of Equals
            //Something like this:

            //return MyComparer.Compare( ... ) == 0 ? this : null;

            return item.Equals(this.Name) ? this : null;
        }

        public IComponent<T> Remove(T item)
        {
            throw new NotImplementedException();
        }
    }
}
名称空间组合
{
使用制度;
使用System.Collections.Generic;
公共类组件:IComponent
{
公共组件(字符串名称)
{
this.Name=Name;
}
公共字符串显示(int深度)
{
返回新字符串('-',深度)+this.Name+“\n”;
}
公共字符串名称{get;set;}
公共IComparer MyComparer{get;私有集;}
//公共IComparer myComparer{set;}
公共作废添加(IComponent项)
{ 
抛出新的NotImplementedException();
}
公共IComponent查找(T项)
{
//这里我想使用comparer对象,而不是Equals
//大概是这样的:
//返回MyComparer.Compare(…)==0?此值为空;
返回项.Equals(this.Name)?this:null;
}
公共IComponent删除(T项)
{
抛出新的NotImplementedException();
}
}
}
最后是我的主要功能:

namespace composite
{
    class Program
    {
        static void Main(string[] args)
        {
            //Creating custom comparer and pass to the constructor composite?
            IComparer<string> myComparer = new ...


            IComponent<string> comp1 = new Component<string>("Komponenta 1");
            IComponent<string> comp2 = new Component<string>("Komponenta 2");
            IComponent<string> comp3 = new Component<string>("Komponenta 3");
            IComponent<string> comp4 = new Component<string>("Komponenta 4");
            IComponent<string> comp5 = new Component<string>("Komponenta 5");

            IComponent<string> composite = new Composite<string>("Composite 1");

            IComponent<string> composite2 = new Composite<string>("Composite 2");

            composite.Add(comp1);
            composite.Add(comp2);
            composite.Add(comp3);
            composite.Add(comp4);
            composite.Add(comp5);

            composite2.Add(comp1);
            composite2.Add(comp2);
            composite2.Add(comp3);
            composite2.Add(comp4);
            composite2.Add(comp5);

            composite.Add(composite2);

            Console.Write(composite.Display(0));
        }
    }
}
名称空间组合
{
班级计划
{
静态void Main(字符串[]参数)
{
//创建自定义比较器并传递到构造函数组合?
IComparer myComparer=新建。。。
IComponent comp1=新组件(“Komponta 1”);
IComponent comp2=新组件(“Komponta 2”);
IComponent comp3=新组件(“Komponta 3”);
IComponent comp4=新组件(“Komponta 4”);
IComponent comp5=新组件(“Komponta 5”);
IComponent复合材料=新复合材料(“复合材料1”);
IComponent composite2=新复合材料(“复合材料2”);
添加(comp1);
添加(comp2);
添加(comp3);
添加(comp4);
添加(comp5);
复合2.添加(复合1);
复合2.添加(复合2);
复合2.添加(复合3);
复合2.添加(复合4);
复合2.添加(复合5);
复合.添加(合成2);
Console.Write(composite.Display(0));
}
}
}
你能帮我实现自定义比较器和传递查找方法吗? 这是好办法还是不好


非常感谢

这里的主要问题是:

  • 组件具有
    名称
    属性
  • 组件不使用泛型类型参数
    t
  • Find
    方法获取类型为
    T
    的泛型项以进行查找和比较 它带有组件名称-这仅适用于
    IComponent
因此,最简单的(也是我最喜欢的)解决方案是去掉比较器。 相反,我将使用谓词定义find方法(如注释中所述)

但你要的是比较器

因此,需要进行一些调整:

  • IComponent
    中定义属性
    T Data{get;set;}
    ,并 在
    组件
    组合

  • 如果需要,请从
    IComparer
    切换到
    IEqualityComparer
    因为您希望搜索相等的组件,而不是比较元素

  • 相应地更改删除方法

在代码中(稍微缩短):


有什么问题吗?添加第二个argum
public class DefaultComparer<T> : IEqualityComparer<IComponent<T>>
{

    public bool Equals(IComponent<T> x, IComponent<T> y)
        => EqualityComparer<T>.Default.Equals(x.Data, y.Data);

    public int GetHashCode(IComponent<T> obj)
        => EqualityComparer<T>.Default.GetHashCode(obj.Data);

}

public class NameComparer<T> : IEqualityComparer<IComponent<T>>
{
    public bool Equals(IComponent<T> x, IComponent<T> y)
        => string.Equals(x.Name, y.Name);

    public int GetHashCode(IComponent<T> obj)
        => (obj.Name ?? string.Empty).GetHashCode();
}
        var element1 = composite.Find(new Component<string>("Komponenta 5"), new NameComparer<string>());
        Console.WriteLine(element1.Name);
        var element2 = composite.Find(t => string.Equals(t.Name, "Komponenta 5"));
        Console.WriteLine(element2.Name);