Generic SaveObject

Generic SaveObject

Old forum URL: forums.lhotka.net/forums/t/5845.aspx


alef posted on Friday, November 21, 2008

I'm trying to implement a generic SaveObject method :

    private void SaveObject<T>(T obj) where T : Csla.Core.ISavable
    {

      try
      {
        obj = (T)obj.Save();
      }
      catch (Csla.DataPortalException ex)
      {

        //process normal data exceptions here
      }
      catch (Exception ex)
      {
        //process unexpected exceptions here
      }
    }

Why does the Save method of the interface ISaveble returns an object (csla book 2.1). Why it is not using also generics? Like the following :
public interface ISaveble<T>
{
     T Save();
     event EventHandler<SavedEventArgs> Saved;
}

If that would be the case I could write the following:
    private void SaveObject<T>(T obj) where T : Csla.Core.ISavable
    {

      try
      {
        obj = obj.Save<T>();
      }
      catch (Csla.DataPortalException ex)
      {

        //process normal data exceptions here
      }
      catch (Exception ex)
      {
        //process unexpected exceptions here
      }
    }

RockfordLhotka replied on Saturday, November 22, 2008

It doesn't use a generic type because generics are not polymorphic. And the intent of ISavable is to enable polymorphic code that can save any savable object.

Basically, it is intended to enable what you are doing, but without the need for any generic types. So you could create a base Page/Form/Window class that "just knows" how to save a business object, regardless of the type of that object.

Generics are a fine thing, but they have some serious negative side-effects at times, the most notable being the loss of polymorphism.

alef replied on Monday, November 24, 2008

I'm trying to understand a little bit more "generics are not polymorphic".
So I've created a little example where you can see a method SaveObject which takes an ISavable<T> as argument. The only thing which is not nice is that you have to give the type eg Customer to the SaveObject method but ISavable is using generics. So do you mean it is not possible to call SaveObject without given the type Customer?
I'm still having some problems to understand generics. Can you explain a little bit more?

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication2
{
  class Program
  {
    static void Main(string[] args)
    {

      Customer customer = new Customer();
      SaveObject<Customer>(customer);
    }

    private static void SaveObject<T>(ISavable<T> obj)
    {
      obj.Save();
    }

  }
}


------------Interface ISavable --------------------------------------

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication2
{
  interface ISavable<T>
  {
    T Save();
  }
}

------------Class Entity which implements ISavable --------------------------------------

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication2
{
  public abstract class Entity<T> : ISavable<T>
  {


    #region ISavable<T> Members

    public T Save()
    {
      Console.WriteLine("Object " + typeof(T).Name + "is been saved");
      return default (T);
    }

    #endregion
  }
}

------------Class Customer  --------------------------------------

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication2
{
  public class Customer:Entity<Customer>
  {
  }
}




Copyright (c) Marimer LLC