如何检查项目是否已在存储库列表中?

时间:2019-07-19 17:54:46

标签: c#

好,所以这里有一些例外,我无法在DvdController.cs中使用List<Dvd> Dvds = _dvds.ReadAll();并检查dvd是否已包含在列表中,以查看其是否包含dvd信息。即使我确实这样做了,它也无法按我的预期工作。即使我检查该信息是否在列表中并尝试将其停止,它仍会将其添加到列表中。 Dvd.cs确实将Id递增了一个。我想知道解决方案吗?

DvdController.cs

...
private void CreateDvd() //Create
    {
        var myView = new DvdView();
        var dvdInfos = myView.GetNewDvdInfo();

        _dvds.Create(dvdInfos);
        DisplayDvds();
    }
...

DvdRepository.cs

public class DvdRepository
{
    private static List<Dvd> dvds = new List<Dvd>()
    {
        new Dvd("Batman", 2010, "Bruce", 4 ),
        new Dvd("Superman", 2009, "John", 4),
        new Dvd("Wonderwoman", 2012, "Omar", 4)
    };
    public Dvd Create(Dvd dvd)
    {
        if (dvds.Contains(dvd))
        {
            Console.WriteLine("duplicate"); //not working
        }
        else
            dvds.Add(dvd);

        return dvds.FirstOrDefault(d => d.Id == dvd.Id);
    }
    public List<Dvd> ReadAll()
    {
        return dvds;
    }
...

Dvd.cs

public class Dvd
    {
        public Dvd(string title, int releaseyear, string director, float rating)
        {
            Id = Interlocked.Increment(ref globalId);
            Title = title;
            ReleaseYear = releaseyear;
            Director = director;
            Rating = rating;
        }

        public static int globalId;
        public int Id { get; private set; }
        public string Title { get; set; }
        public int ReleaseYear { get; set; }
        public string Director { get; set; }
        public float Rating { get; set; }

2 个答案:

答案 0 :(得分:6)

您对if (dvds.Contains(dvd))的检查正在查找该特定对象引用。除非您已经传递了列表中的实际对象,否则它将不起作用。

您需要检查Dvd的唯一标识属性。为此,您需要使用.Any()方法。

if (dvds.Any(x => x.Title == dvd.Title))

答案 1 :(得分:1)

另一个需要更多代码但在将来可能会有所帮助的解决方案是重写Equals类上的GetHashCodeDvd方法。默认情况下,对象使用引用比较来确定相等性。通过覆盖这些方法,我们可以使用自己的逻辑来确定两个Dvd是否相等。

在下面的示例中,我使用了TitleReleaseYearDirector字段,但是您可以根据需要添加其他字段。我还实现了IEquatable<Dvd>,因为它非常简单(只需要添加一个Equals方法,该方法采用类型为Dvd的对象)即可,并且与object.Equals的实现相得益彰: / p>

public class Dvd : IEquatable<Dvd>
{
    public Dvd(string title, int releaseyear, string director, float rating)
    {
        Id = Interlocked.Increment(ref globalId);
        Title = title;
        ReleaseYear = releaseyear;
        Director = director;
        Rating = rating;
    }

    public static int globalId;
    public int Id { get; private set; }
    public string Title { get; set; }
    public int ReleaseYear { get; set; }
    public string Director { get; set; }
    public float Rating { get; set; }

    public bool Equals(Dvd other)
    {
        return other != null &&
               Title == other.Title &&
               ReleaseYear == other.ReleaseYear &&
               Director == other.Director;
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as Dvd);
    }

    public override int GetHashCode()
    {
        return ((Title?.GetHashCode() ?? 17) * 17 +
                ReleaseYear.GetHashCode()) * 17 +
               (Director?.GetHashCode() ?? 17);
    }
}

有了这些更改,我们不必担心记住在评估Dvd查询中的两个Linq对象时需要比较哪些字段(以及是否要添加更多属性)为了进行比较,我们只需要在一个地方进行操作,而不是在整个代码中进行搜索),我们可以做类似if (firstDvd.Equals(secondDvd)) { // do something if they're equal }的事情。

现在,我们可以使用原始代码中定义的Contains方法。例如:

private static void Main()
{
    var repo = new DvdRepository();
    repo.Create(new Dvd("Batman", 2010, "Bruce", 2));
}

输出到控制台:"duplicate"