調べ物した結果

現役SEが仕事と直接関係ないことを調べた結果とか感想とか

C#のジェネリックの制約条件がよくわからなくなったから試してみた(敗北。打開できず)

発端

入れ子になっているコレクションクラスのinterfaceのwhereの書き方がどうすればいいのかわかなくなった。
(そもそもそーゆー実装がダメなのかもしれないけど

先に・・・

答えはない。だれか教えてほしい。

ソースの基本型

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace ClassLibrary1
{

    public class VOLists
    {
        // このクラスでIVOCollections<T>を使うとする。 Listで持ちたい
        public List<VOList> Collections { get; set; }
    }

    public class VOList : IVOCollection<List<VO>>
    {
        public List<VO> Collection { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    }

    public class VOObserbable : IVOCollection<ObservableCollection<VO>>
    {
        public ObservableCollection<VO> Collection { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    }

    /// <summary>適当ValueObject</summary>
    public class VO { }

    /// <summary>VOのコレクション</summary>
    public interface IVOCollection<T> where T:ICollection<VO>
    {
        T Collection { get; set; }
    }

    /// <summary>VOのコレクションのコレクション</summary>
    public interface IVOCollections<T> // このクラスの条件どうするんじゃい。というのが本題
    {
        T Collections { get; set; }
    }
}

とりあえず何も制約がない場合

    public class VOLists : IVOCollections<List<VOList>>
    {
        // このクラスでIVOCollections<T>を使うとする。 Listで持ちたい
        public List<VOList> Collections { get; set; }
    }

    /// <summary>VOのコレクションのコレクション</summary>
    public interface IVOCollections<T> // このクラスの条件どうするんじゃい。というのが本題
    {
        T Collections { get; set; }
    }

ビルドもすんなり通ってくれる。そらそう。

エラーになるやつ1

    public class VOLists : IVOCollections<List<VOList>>
    {
        // このクラスでIVOCollections<T>を使うとする。 Listで持ちたい
        public List<VOList> Collections { get; set; }
    }

    /// <summary>VOのコレクションのコレクション</summary>
    public interface IVOCollections<T> // このクラスの条件どうするんじゃい。というのが本題
        where T : ICollection<IVOCollection<ICollection<VO>>>
    {
        T Collections { get; set; }
    }

以下のエラーになる。ICollection と VOListの方がほにゃらら。ということだと思う。


重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態
エラー CS0311 型 'System.Collections.Generic.List' はジェネリック型またはメソッド 'IVOCollections' 内で型パラメーター 'T' として使用できません。'System.Collections.Generic.List' から 'System.Collections.Generic.ICollection>>' への暗黙的な参照変換がありません。


VOListクラス側ででIVOCollection>として明示してるんだから、やってくれてもよくない?
とおもったりすんじゃがだめらしい。

整理。やりたいこと、状況

IVOCollectionは ICollectionで縛りをかけている。これにより何でもかんでもコレクションを
ぶち込むことを防いでいる。
同様に
IVOCollectionsもICollectionとして、IVOCollection以外のコレクションは保証しないことを明示したいが
うまくいかない。ふもも。

試しに2重に宣言するようにしてみる。

TitleVOでそうしているように、IVOCollectionを使う際の型の明示が甘いから
コンパイラーで判断できなくなっていると予想。

    public class VOLists : IVOCollections<List<VOList>, List<VO>>
    {
        public List<VOList> Collections { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    }

    /// <summary>VOのコレクションのコレクション</summary>
    public interface IVOCollections<T1, T2> 
        where T1 : ICollection<T2>
        where T2 : IVOCollection<ICollection<VO>>
    {
        T1 Collections { get; set; }
    }

だめ。記載自体も冗長なので、うまくいっていてもなんか気持ち悪いので
まーそうよね。。。

なにもわかっちゃいないが・・・インターフェースでの制約をあきらめる。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace ClassLibrary1
{
    public class VOLists<T1, T2> : IVOCollections<T1>
        where T1 : List<VOList<T2>>
        where T2 : List<VO>
    {
        public T1 Collections { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    }

    /// <summary>VOのコレクションのコレクション</summary>
    public interface IVOCollections<T> 
    {
        T Collections { get; set; }
    }

    public class VOList<T> : IVOCollection<T> where T : List<VO>
    {
        public T Collection { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    }

    public class VOObserbable : IVOCollection<ObservableCollection<VO>>
    {
        public ObservableCollection<VO> Collection { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    }

    /// <summary>適当ValueObject</summary>
    public class VO { }

    /// <summary>VOのコレクション</summary>
    public interface IVOCollection<T>
    {
        T Collection { get; set; }
    }
}

これならとおる。なにもわかっちゃいねぇ・・・うーん。なんだろう。うーん。
interfaceある意味もない気がしてきたし・・・うーん。

けつろん

よくわからん。interfaceの実装を誤解している気もするし、
そもそも設計がよくない気もする。わからん。