简体   繁体   中英

Why can't I add this instance of a generic type to a collection?

I have two abstract types with a many to many relationship:

public abstract class Experiment<T> where T : Sample
{
    private List<T> _Samples = new List<T>;
    public IReadOnlyCollection<T> Samples {
        get { return _Samples.AsReadOnly(); }
    }

    public void AddSample(T sample)
    {
        _Samples.Add(sample); 
        sample.Experiments.Add(this); // The problem lies here
    }
}

public abstract class Sample
{
    private List<Experiment<Sample>> _Experiments = new List<Experiment<Sample>>;
    public ICollection<Experiment<Sample>> Experiments {
        get { return _Experiments; }
    }
}

As you can see, an experiment accepts a type parameter that is a subclass of Sample . What I am trying to do is this: whenever an instance of a subtype of Sample is added to an Experiment , the Experiment should correspondingly be added to the Experiments collection of the Sample .

The problem arises when I try to add an instance of an Experiment<T> to a collection that is List<Experiment<Sample>> . Since T is a subtype of Sample , I was assuming there wouldn't be a problem. What actually happens is the following:

Value of type 'Experiment<T>' cannot be converted to 'Experiment<Sample>`

My question is whether there is a way to work around this problem, or to better model the relationship between these entities.

public class Experiment<T> where T : Sample
{
    private List<T> _Samples = new List<T>();
    public IReadOnlyCollection<T> Samples
    {
        get { return _Samples.AsReadOnly(); }
    }

    public Experiment()
    {
    }

    public Experiment(IEnumerable<T> samples)
    {
        _Samples = samples.ToList();
    }

    public void AddSample(T sample)
    {
        _Samples.Add(sample);
        sample.Experiments.Add(new Experiment<Sample>(_Samples)); // The problem lies here
    }
}

public abstract class Sample
{
    private List<Experiment<Sample>> _Experiments = new List<Experiment<Sample>>();
    public ICollection<Experiment<Sample>> Experiments
    {
        get { return _Experiments ; }
    }
}

By adding some constructors and modifying the Experiments collection in Sample I think I was able to achieve what you're looking for. Now you can use the following code

public class MySample : Sample{}

public class MyExperiment : Experiment<MySample>{}

MyExperiment me = new MyExperiment();
me.AddSample(new MySample());

So I think the fix is this:

public abstract class Experiment<T> where T : Sample<T>
{
    private List<T> _Samples;
    public IReadOnlyCollection<T> Samples {
        get { return _Samples.AsReadOnly(); }
    }

    public void AddSample(T sample)
    {
        _Samples.Add(sample); 
        sample.Experiments.Add(this); // The problem lies here
    }
}

public abstract class Sample<T> where T : Sample<T>
{
    private List<Experiment<T>> _Experiments;
    public ICollection<Experiment<T>> Experiments {
        get { return _Experiments; }
    }
}

Because the two types are dependent on each other then they need to share the same generic type.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM