Search code examples
c#interfacecompositiondelegation

In c#, is it possible for a type to expose an interface of its member's type as its own


I am not sure how to even clearly phrase this question, so here are two more versions of the same question:

  • Can a struct/class implement an interface by delegating to its field/property?
  • Can I map an interface implemented by a field/property type to its struct/class?

Here is a code example with pseudo-syntax added to hopefully show what I mean:

public class School : IEnumerable<Student>
{
    private List<Student> students expose IEnumerable<Student>;
    ...
}

If this is not currently possible, is it potentially possible? ...or are there some serious issues with this approach? I reckon this could be just syntactic sugar to get rid of boiler plate code which would otherwise be functionally identical. Example:

public class School : IEnumerable<Student>
{
    private List<Student> students;
    ...
    public IEnumerator<Student> GetEnumerator() { return students.GetEnumerator(); }
    IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}

}

This is of course a very contrived and minimal example. The benefits would be greater when composing interfaces designed for it, especially when there are a lot of methods to "map".

UPDATE: I am aware that I provided a terrible example, but I just wanted to use the simplest example possible. The core of the question is not about a specific scenario. Having said that, my example is bad; so, to better help people who like to see a good example accompany a question, here is a slightly better one:

public interface IValidPeriod
{
    DateTime ValidFrom { get; }
    DateTime ValidTo { get; }
    DateTime ValidThrough { get; }
    int DaysValid { get; }
}

public class ValidPeriod : IValidPeriod
{
    public DateTime ValidFrom { get; private set; }
    public DateTime ValidTo { get; private set; }
    public DateTime ValidThrough { get { return ValidTo.AddDays(1); } }
    public int DaysValid { get { return (ValidTo - ValidFrom).Days; } }

    public ValidPeriod(DateTime from, DateTime to)
    {
        ValidFrom = from;
        ValidTo = to;
    }
}

public class Agreement : IValidPeriod
{
    ...
    public ValidPeriod ValidPeriod { get; private set; } exposes IValidPeriod;
    ...
}

public class Contract : IValidPeriod, ICancellable
{
    private Agreement agreement exposes IValidPeriod;
    ...
}

public class Payment : IValidPeriod, ICancellable
{
    public DateTime StartDate { get; set; }

    private ValidPeriod validPeriod
    {
        get { return new ValidPeriod(StartDate, DateTime.Max); }
    } exposes IValidPeriod;
    ...
}

public static class SomeUtility
{
    public static void CancelIfValidBefore<T>(List<T> items, DateTime date)
        where T : IValidPeriod, ICancellable
    {
        ...
    }
}

Solution

  • I'm posting an answer to my own question thanks to an implicit answer provided by Wiktor Zychla in a comment to the question via a link:

    github.com/dotnet/roslyn/issues/13952

    The link is to a proposal for for a feature which is exactly what I had in mind when I posted this question. So the answer to my question is - no, it is not possible.

    The link contains a good discussion and links to further information. The proposed syntax is the only thing I would reconsider. One of the commenters there provided a link showing Kotlin syntax for this feature, which I think is by far the best and is better than what I came up with (although I wasn't proposing a syntax, just trying to illustrate my question).

    Here is an updated version of my delegation example using Kotlin's syntax:

    public class School : IEnumerable<Student> by students
    {
        private List<Student> students;
        ...
    }