1

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
    {
        ...
    }
}
tomosius
  • 1,369
  • 12
  • 18
  • 4
    See https://github.com/dotnet/roslyn/issues/13952 – Wiktor Zychla Mar 16 '17 at 09:32
  • The first question is why do you think `School` **is** an enumeration of `Student`s? It has students, but also teachers and other personal. `School` shouldn't implement that interface, having public method returning students is more than enough. Unless you have a better example I doubt this feature-request is really that needed, it's basically a problem of attempted solution. Automatically implementing *few* methods? I can do it myself and I do really like to see this implementation explicitly, not via some mysterious `expose` operators. – Sinatr Mar 16 '17 at 10:02
  • There is no "delegation", an interface does not implement anything. It merely demands that you provide an implementation. Deriving your class from `List` would be the simple way, but with the usual hangup that you cannot override the Add() method. Delegating to a private List is fine and simple to do. – Hans Passant Mar 16 '17 at 11:46

2 Answers2

2

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;
    ...
}
tomosius
  • 1,369
  • 12
  • 18
  • The "public interface" of the class should not how how it is implemented, hence I don't like Kotlin's syntax. PS, A better example would be a student that contains a person object, as a teacher could also contain a person object. If a person is both a teacher and a student, both the teacher object and the student object would contain the same person object. (And use it for GetName() for example.) – Ian Ringrose Mar 20 '17 at 13:47
0
  1. No this is not possible the way you have described. How do you tell the compiler that one "expose" operator takes precedence over any other? What happens when you code two internal objects that expose the same interface? Or when two "exposed" objects have share properties or functions of the same name?

  2. What do you gain from this notation? It turns out that what you are asking is sort of possible, with 1 restriction. That is you can only "expose" one type... We call this inheritance :) You will get the same logical outcome if you inherit from the type that you want to "expose". What you are describing is to replicate the implementation of an interface, but you want to hide that fact from outside the class? This sounds to me more of an anti pattern that will hinder more than it will help.

  3. It is far simpler to expose these objects as public properties then you dont have to make any special considerations or check for duplications across the type interfaces. The only reason to "map" properties in a manner like this would be because you want to replace or modify the behaviour of the underlying type. Otherwise you would save the hassle and simply expose it

  4. Your class implementing IEnumerable IS NOT A GOOD DESIGN and there will be many experienced developers clawing at their eys or simply down voting when they see this question

I had to look it up but I remember a similar request on SO: Why not inherit from List

There is some good healthy discussions in that thread and many others on SO around this topic. We are your friends here, but this is a can of worms that many of us would prefer not be opened in C#. I fully support exploration of this in other languages and would enjoy reading about the journey but ultimately we are not saving enough keys strokes nor are we offering a construct that would allow for faster compilation or runtime strategies to make this a good feature request

Community
  • 1
  • 1
Chris Schaller
  • 13,704
  • 3
  • 43
  • 81
  • 1
    1. I don't see why it is not possible. If you consider it as a syntactic sugar, then compiler may simply expand it into a list of methods with respective calls to that field. Then all conflicts will be resolved in usual way. 2. Why is it hidden from the outside? If the class implements interface then it exposes implemented members 3. I don't see why it is simpler to write all these members by hand 4. This is a contrived example. I'm not advocating this feature but I don't understand all the critique. – username Mar 16 '17 at 10:54
  • Ok, so it is possible to make it a feature and make the compiler aware of all this... but what have we gained? Point 3 above is IMO a really hard argument to ignore, if you are going to simply forward ALL properties and methods from the exposed type, then why isn't it just a property? But also how to we handle overrides, do we allow the class to selectively override some properties and all others simply get propagated through from the exposed type? I feel like this sort of feature undermines the stability and simplicity of our c# language. – Chris Schaller Mar 16 '17 at 11:01
  • If all you want to achieve is to save some key strokes, then you should consider injection techniques via attributes to re-write the IL as it is compiled. That is certainly doable right now. I think that the uncertainty of this feature would make some code harder to interpret. – Chris Schaller Mar 16 '17 at 11:03
  • My last response :) You are right, it is not simpler to write these out by hand, I am questioning why you wouldn't make the whole exposed type a property on the class and be done with it. You example of inheriting from IEnumerable is a big red flag, you are trying to do something in a really complicated manner, just make Students a property of School and be done with it. (don't attempt to make School inherit from IEnumerable) – Chris Schaller Mar 16 '17 at 11:09