Practical advantage of generics vs interfaces

前端 未结 8 1441
梦毁少年i
梦毁少年i 2020-11-29 02:35

What would be a practical advantage of using generics vs interfaces in this case:

void MyMethod(IFoo f) 
{
}

void MyMethod(T f) : where T : IFoo
{
         


        
相关标签:
8条回答
  • 2020-11-29 03:24

    2 years later I found a very simple and useful case. Consider this common pattern:

    class MyClass : IDisposable {
    
         public void Dispose() {
             if (m_field1 != null) {
                 m_field1.Dispose();
                 m_field1 = null;
             }
             if (m_field2 != null) {
                 m_field2.Dispose();
                 m_field2 = null;
             }
             // etc
         }
    }
    

    I've always wanted to write a helper method to avoid having to write all this boilerplate for every field:

    class MyClass : IDisposable {
    
        static void IfNotNullDispose(ref IDisposable disposable) {
            if (disposable != null) {
                disposable.Dispose();
                disposable = null;
            }
        }
    
        public void Dispose() {
             IfNotNullDispose(ref m_field1);
             IfNotNullDispose(ref m_field2);
             // etc
        }
    }
    

    Unfortunately this is illegal in C# because you cannot use an interface for ref parameters, you must use the concrete type you'll pass in and nothing else. So you'd have to write a different method for every single type of field you want to dispose. Oh wait that's exactly what generics do for you:

    static void IfNotNullDispose<T>(ref T disposable) where T: class, IDisposable {
        if (disposable != null) {
            disposable.Dispose();
            disposable = null;
        }
    }
    

    Now everything works as intended!

    0 讨论(0)
  • 2020-11-29 03:33

    In this particular case, there is no benefit. In general you wouldn't specify this at a method level, but at a class level. E.g.,

    public interface IFoo {
            void DoSomethingImportant();
        }
    
        public class MyContainer<T> where T : IFoo {
            public void Add(T something){
                something.DoSomethingImportant();
                AddThisThing(something);
            }
    
            public T Get() {
                T theThing = GetSomeKindOfThing();
                return theThing;
            }
        }
    

    Notice that we require T to implement IFoo because of the Add method where we need to call the DoSomethingImportantMethod implemented by IFoo.

    But notice in the Get method that we will return the T provided by end user of this class instead of a plain old IFoo, which alleviates the need for the developer to always cast to their actual concrete T.

    Example:

    public class Bar : IFoo{
      //....
    }
    
    MyContainer<Bar> m = new MyContainer<Bar>();
    //stuff happens here
    Bar b = m.Get();
    

    Note that if I was just returning an IFoo, then I would have to do this at the last line instead:

    Bar b = (Bar) m.Get();
    
    0 讨论(0)
提交回复
热议问题