locked
Generic Interface RRS feed

  • Question

  • User265788195 posted

    When should we use generic interfaces? Any good example for dummies?

    Monday, August 15, 2011 2:26 PM

Answers

  • User1292382518 posted

    Hi Nissan,

    Generic interface are used when the interface exhibits the common behaviour for multiple different types. One small example that you might have already used multiple time with your project. You might have used different manager patterns for different models e.g. DepartmentManager for Department & UserManager for User. Let's rewrite it with the generic interface term ...

        /// <summary>
        /// Core implementation having default set of attributes
        /// </summary>
        class AbstractRecord
        {
            public string Id { get; set; }
            public string Name { get; set; }
        }
        /// <summary>
        /// Multiple derived implementaton
        /// </summary>
        class Employee : AbstractRecord
        {
        }
        /// <summary>
        /// Multiple derived implementaton
        /// </summary>
        class Department : AbstractRecord
        {
        }
        /// <summary>
        /// Common Manager for all the types that extend AbstractRecord class and having parameterless constructor
        /// </summary>
        /// <typeparam name="T">The generic type that extends AbstractRecord class and having parameterless constructor</typeparam>
        interface IManager<T> where T:AbstractRecord, new()
        {
            void Add(T obj);
            void Update(T obj);
            void Delete(string id);
        }
    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, August 15, 2011 2:45 PM
  • User-401756089 posted

    Hi,  look what Jeffrey Richter says about generic interfaces:

    1) Generic interfaces offer great compile-time type safety
    Some interfaces (such as the non-generic IComparable interface) define methods that have Object parameters or return types. When code calls these interface methods, a reference to an instance of any type can be passed. But this is usually not desired. The following code demonstrates:

    private void SomeMethod1() {
        Int32 x = 1, y = 2;
        IComparable c = x;
        // CompareTo expects an Object; passing y (an Int32) is OK
        c.CompareTo(y); // y is boxed here
        // CompareTo expects an Object; passing "2" (a String) compiles
        // but an ArgumentException is thrown at runtime
        c.CompareTo("2");
    }

    Obviously, it is preferable to have the interface method strongly typed, and this is why the FCL includes a generic IComparable<in T> interface. Here is the new version of the code revised by using the generic interface:

    private void SomeMethod2() {
        Int32 x = 1, y = 2;
        IComparable<Int32> c = x;
        // CompareTo expects an Int32; passing y (an Int32) is OK
        c.CompareTo(y); // y is not boxed here
        // CompareTo expects an Int32; passing "2" (a String) results
        // in a compiler error indicating that String cannot be cast to an Int32
        c.CompareTo("2"); // Error
    }

    2) Second benefit of generic interfaces is that much less boxing will occur when working with value types. Notice in SomeMethod1 that the non-generic IComparable interface’s CompareTo method expects an Object; passing y (an Int32 value type) causes the value in y to be boxed. However, in SomeMethod2, the generic IComparable<in T> interface’s CompareTo method expects an Int32; passing y causes it to be passed by value, and no boxing is necessary.

    3) The third benefit of generic interfaces is that a class can implement the same interface multiple times as long as different type parameters are used. The following code shows an example of how useful this could be:

    using System;
    // This class implements the generic IComparable<T> interface twice
    public sealed class Number: IComparable<Int32>, IComparable<String> {
        private Int32 m_val = 5;
        // This method implements IComparable<Int32>'s CompareTo
        public Int32 CompareTo(Int32 n) {
        return m_val.CompareTo(n);
    }
    
    // This method implements IComparable<String>'s CompareTo
        public Int32 CompareTo(String s) {
            return m_val.CompareTo(Int32.Parse(s));
        }
    }
    
    public static class Program {
        public static void Main() {
            Number n = new Number();
            // Here, I compare the value in n with an Int32 (5)
            IComparable<Int32> cInt32 = n;
            Int32 result = cInt32.CompareTo(5);
            // Here, I compare the value in n with a String ("5")
            IComparable<String> cString = n;
            result = cString.CompareTo("5");
        }
    }

    An interface’s generic type parameters can also be marked as contravariant and covariant, which allows even more flexibility for using generic interfaces. For more about contravariance and covariance, see this link: http://msdn.microsoft.com/en-us/library/dd799517.aspx

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, August 15, 2011 5:43 PM

All replies

  • User1292382518 posted

    Hi Nissan,

    Generic interface are used when the interface exhibits the common behaviour for multiple different types. One small example that you might have already used multiple time with your project. You might have used different manager patterns for different models e.g. DepartmentManager for Department & UserManager for User. Let's rewrite it with the generic interface term ...

        /// <summary>
        /// Core implementation having default set of attributes
        /// </summary>
        class AbstractRecord
        {
            public string Id { get; set; }
            public string Name { get; set; }
        }
        /// <summary>
        /// Multiple derived implementaton
        /// </summary>
        class Employee : AbstractRecord
        {
        }
        /// <summary>
        /// Multiple derived implementaton
        /// </summary>
        class Department : AbstractRecord
        {
        }
        /// <summary>
        /// Common Manager for all the types that extend AbstractRecord class and having parameterless constructor
        /// </summary>
        /// <typeparam name="T">The generic type that extends AbstractRecord class and having parameterless constructor</typeparam>
        interface IManager<T> where T:AbstractRecord, new()
        {
            void Add(T obj);
            void Update(T obj);
            void Delete(string id);
        }
    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, August 15, 2011 2:45 PM
  • User-401756089 posted

    Hi,  look what Jeffrey Richter says about generic interfaces:

    1) Generic interfaces offer great compile-time type safety
    Some interfaces (such as the non-generic IComparable interface) define methods that have Object parameters or return types. When code calls these interface methods, a reference to an instance of any type can be passed. But this is usually not desired. The following code demonstrates:

    private void SomeMethod1() {
        Int32 x = 1, y = 2;
        IComparable c = x;
        // CompareTo expects an Object; passing y (an Int32) is OK
        c.CompareTo(y); // y is boxed here
        // CompareTo expects an Object; passing "2" (a String) compiles
        // but an ArgumentException is thrown at runtime
        c.CompareTo("2");
    }

    Obviously, it is preferable to have the interface method strongly typed, and this is why the FCL includes a generic IComparable<in T> interface. Here is the new version of the code revised by using the generic interface:

    private void SomeMethod2() {
        Int32 x = 1, y = 2;
        IComparable<Int32> c = x;
        // CompareTo expects an Int32; passing y (an Int32) is OK
        c.CompareTo(y); // y is not boxed here
        // CompareTo expects an Int32; passing "2" (a String) results
        // in a compiler error indicating that String cannot be cast to an Int32
        c.CompareTo("2"); // Error
    }

    2) Second benefit of generic interfaces is that much less boxing will occur when working with value types. Notice in SomeMethod1 that the non-generic IComparable interface’s CompareTo method expects an Object; passing y (an Int32 value type) causes the value in y to be boxed. However, in SomeMethod2, the generic IComparable<in T> interface’s CompareTo method expects an Int32; passing y causes it to be passed by value, and no boxing is necessary.

    3) The third benefit of generic interfaces is that a class can implement the same interface multiple times as long as different type parameters are used. The following code shows an example of how useful this could be:

    using System;
    // This class implements the generic IComparable<T> interface twice
    public sealed class Number: IComparable<Int32>, IComparable<String> {
        private Int32 m_val = 5;
        // This method implements IComparable<Int32>'s CompareTo
        public Int32 CompareTo(Int32 n) {
        return m_val.CompareTo(n);
    }
    
    // This method implements IComparable<String>'s CompareTo
        public Int32 CompareTo(String s) {
            return m_val.CompareTo(Int32.Parse(s));
        }
    }
    
    public static class Program {
        public static void Main() {
            Number n = new Number();
            // Here, I compare the value in n with an Int32 (5)
            IComparable<Int32> cInt32 = n;
            Int32 result = cInt32.CompareTo(5);
            // Here, I compare the value in n with a String ("5")
            IComparable<String> cString = n;
            result = cString.CompareTo("5");
        }
    }

    An interface’s generic type parameters can also be marked as contravariant and covariant, which allows even more flexibility for using generic interfaces. For more about contravariance and covariance, see this link: http://msdn.microsoft.com/en-us/library/dd799517.aspx

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, August 15, 2011 5:43 PM