質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.87%

  • C#

    6228questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

C# List<T> の要素比較

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 124

fuku1357

score 1

C#にてFormアプリを開発中です。

List<T>について二つのリストの要素が等しいかを判定する方法は無いでしょうか。

SequenceEqualだと参照比較になってしまい、実データの比較ができません。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • papinianus

    2018/07/12 20:19

    Tはどんな型ですか?自作Classですか?

    キャンセル

  • fuku1357

    2018/07/12 20:21

    自作Classです。

    キャンセル

  • SurferOnWww

    2018/07/13 09:04

    「二つのリストの要素」とはなんですか? なにと何を何の目的で比較するのですか? List<T> に Distinct を適用したいとか?

    キャンセル

回答 2

+2

こっちのオーバーロードを使ってIEqualityComparerを渡せばよいかと。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/12 20:30

    もしくは、自作クラス側でEqualsメソッドをオーバーライドするかですね。

    キャンセル

  • 2018/07/12 21:08

    おっしゃるとおりですね。
    質問者様に伝えるという観点で言えば、SequenceEqualだから参照比較しかできないのではなく、T型のEqualsが参照比較になっていることが、やりたいことができない原因なので「IEquatableを実装する」が本筋のように思えます。
    それができないような場合、あるいは一過的でそこまでしたくない場合などを考えると比較方法を渡すが選択肢にあがるのかなと。

    キャンセル

  • 2018/07/13 09:09

    自作クラス毎にIEqualityComparerの派生クラス用意するのがなと思ったら
    汎用的なクラスを作ってる方がいました。

    https://qiita.com/s-matsuba/items/1ee6bcc1bc5d721fc978

    ただ、いまいち使い方がわからないので教えて欲しいです。

    キャンセル

  • 2018/07/13 23:13

    自作クラスがどのようなものであるかにもよりますが、オブジェクト指向って基本的にクラスごとにIEqualityComparerとかIEquatableの実装とかをする思想だと思っています。
    既に解決していますが、`public static bool ValueEquals(testclass x, testclass y)`は、やはりクラスごとに実装するわけですよね。
    ジャストアイデアですが、そのPOCOは
    ・structにはできないか
    ・基底クラスでIEqutableかIEqualityComparerのデフォルト実装を持てないか(そういうデータにできないか)
    などもご検討くだされば良いのではないかと思います。

    キャンセル

checkベストアンサー

0

コメントにあった汎用クラスの使用方法の簡単な例です。

        static void Main(string[] args)
        {


            List<testclass> List1 = new List<testclass>();
            List<testclass> List2 = new List<testclass>();

            testclass t;

            t = new testclass(1,"ABC","123");
            List1.Add(t);

            t = new testclass(2, "DEF","123");
            List1.Add(t);

            t = new testclass(1, "ABC","456");
            List2.Add(t);

            t = new testclass(2, "DEF","456");
            List2.Add(t);

            GenericEqualityComparer<testclass> EqComp=new GenericEqualityComparer<testclass>(ValueEquals);

            Console.WriteLine(string.Format("SequenceEqual = {0}", List1.SequenceEqual(List2)));
            Console.WriteLine(string.Format("SequenceEqual(IEqualityComparer) = {0}", List1.SequenceEqual(List2,EqComp)));

            Console.ReadKey();
        }


        public static bool ValueEquals(testclass x, testclass y)
        {
            if ((x.Value_A == y.Value_A) && (x.Value_B == y.Value_B))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }


    public class testclass
    {

        public int Value_A;
        public string Value_B;
        public string Value_C;

        public testclass(int valueA,string valueB,string valueC)
        {
            Value_A = valueA;
            Value_B = valueB;
            Value_C = valueC;
        }

    }

    public class GenericEqualityComparer<T> : IEqualityComparer<T>
    {
        private Func<T, T, bool> _predicate;
        private Func<T, int> _gethash;

        public GenericEqualityComparer(Func<T, T, bool> predicate)
            : this(predicate, obj => obj.GetHashCode())
        {
        }
        public GenericEqualityComparer(Func<T, T, bool> predicate, Func<T, int> gethash)
        {
            _predicate = predicate;
            _gethash = gethash;
        }

        public bool Equals(T x, T y)
        {
            return _predicate(x, y);
        }
        public int GetHashCode(T obj)
        {
            return _gethash(obj);
        }
    }

比較部分を外だしして、指定できるような形になっています。
例ではHashCodeの比較部分は実装していませんが、そちらの関数も指定できるようになっています。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/13 10:15

    こちらの回答はpapinianusさんの回答の派生というか、コメント欄では書きにくかった為に書いたものなので、ベストアンサーはpapinianusさんの回答のほうにつけていただいたほうがよいかと思います。

    キャンセル

  • 2018/07/13 10:54

    こんにちは。横から蛇足コメント失礼します。
    このタイプの汎用EqualityComparerを実装する場合、GetHashCodeの省略実装は(_ => 0)とする必要があります。
    そうしないとEqualityの性質を満たせなくなってしまうのです(自分も過去にやってしまいました)。
    参考: https://blogs.msdn.microsoft.com/ericlippert/2011/02/28/guidelines-and-rules-for-gethashcode/

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.87%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C#

    6228questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。