about using compare with generics

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Tony

    about using compare with generics

    Hello!

    Below I have a complete working program.with some simple classes one of
    these is a generic class.

    Now If I want to implement functionallity so I can compare animal with each
    other or with other animal
    for example compare a Chicken with a Cow in some way or a Cow with another
    Cow

    How is that done?
    My attempted strategy is to set a constraint on T in such a way that T is
    required to implement the
    CompareTo method that exist in IEnumerable<T>
    So I change the class definition header for the generic class from this
    definition
    public class Farm<T: IEnumerable<Twh ere T : Animal
    to this
    public class Farm<T: IEnumerable<Twh ere T : Animal, IEnumerable<T>
    I then let Cow, Chicken and SuperCow inherit from IEnumarable
    and then implement CompareTo in each class which is Cow, Chicken and
    SuperCow

    I tried this but run into several problems so my strategy was perhaps
    complete
    wrong.
    So how is the correct way of doing this?


    using System;
    using System.Collecti ons.Generic;
    using System.Collecti ons;
    using System.Text;

    namespace ConsoleApplicat ion15
    {
    class Program
    {
    static void Main(string[] args)
    {
    Farm<Animalfarm = new Farm<Animal>();
    farm.Animal.Add (new Cow("Jack"));
    farm.Animal.Add (new Chicken("Vera") );
    farm.Animal.Add (new Chicken("Sally" ));
    farm.Animal.Add (new SuperCow("Kevin "));

    farm.MakeNoises ();

    Farm<CowdairyFa rm = farm.GetCows();
    dairyFarm.FeedT heAnimals();

    foreach (Cow cow in dairyFarm)
    if (cow is SuperCow)
    ((SuperCow)cow) .Fly();

    Farm<AnimalnewF arm = farm + dairyFarm;
    Console.ReadKey ();
    }
    }

    public abstract class Animal
    {
    string name;
    public Animal(string name)
    { this.name = name; }

    public string Name
    { get { return name; } }

    public abstract void MakeANoise();
    public abstract void Feed();
    }

    public class Chicken : Animal
    {
    public Chicken(string name) : base(name) {}

    public override void MakeANoise()
    { Console.WriteLi ne("{0} says 'cluck!'", Name); }

    public override void Feed()
    { Console.WriteLi ne("{0} has been feed(Chicken)", Name); }
    }

    public class Cow : Animal
    {
    public Cow(string name) : base(name) {}

    public override void MakeANoise()
    { Console.WriteLi ne("{0} says 'moo!'", Name); }

    public override void Feed()
    { Console.WriteLi ne("{0} has been feed(Cow)", Name); }
    }

    public class SuperCow : Cow
    {
    public SuperCow(string name) : base(name) {}

    public void Fly()
    { Console.WriteLi ne("{0} is flying!", Name); }

    public override void MakeANoise()
    { Console.WriteLi ne("{0} says 'here I come to save the day!'",
    Name); }

    public override void Feed()
    { Console.WriteLi ne("{0} has been feed(SuperCow)" , Name); }
    }

    public class Farm<T: IEnumerable<Twh ere T : Animal
    {
    private List<Tanimals = new List<T>();

    public List<TAnimal
    { get { return animals; } }

    public IEnumerator<TGe tEnumerator()
    { return animals.GetEnum erator(); }

    IEnumerator IEnumerable.Get Enumerator()
    { return animals.GetEnum erator(); }


    public void MakeNoises()
    {
    foreach (T animal in animals)
    animal.MakeANoi se();
    }

    public void FeedTheAnimals( )
    {
    foreach (T animal in animals)
    animal.Feed();
    }

    public Farm<CowGetCows ()
    {
    Farm<CowcowFarm = new Farm<Cow>();
    foreach (T animal in animals)
    if (animal is Cow)
    cowFarm.animals .Add(animal as Cow);
    return cowFarm;
    }

    public static Farm<Toperator +(Farm<Tfarm1, Farm<Tfarm2)
    {
    Farm<Tresult = new Farm<T>();
    foreach (T animal in farm1)
    result.Animal.A dd(animal);

    foreach (T animal in farm2)
    if (!result.Animal .Contains(anima l))
    result.Animal.A dd(animal);
    return result;
    }

    public static implicit operator Farm<Animal>(Fa rm<Tfarm)
    {
    Farm<Animalresu lt = new Farm<Animal>();

    foreach(T animal in farm)
    result.Animal.A dd(animal);
    return result;
    }
    }
    }

    //Tony


  • Jon Skeet [C# MVP]

    #2
    Re: about using compare with generics

    On Jun 19, 1:13 pm, "Tony" <johansson.ande rs...@telia.com wrote:
    Here I have put a constraint on the generic class farm as to
    force T to implement the IComparable interface.
    >
    I just wonder can this be done in a better way because I don't have strong
    types in CompareTo method which is impemented in all classes except the abstract
    class ?
    Well, for a start you should think about implementing IComparable<T>
    instead of IComparable.

    But also you really need to think about Marc's questions. How do you
    want a Cow to compare to a Chicken? To another Cow? To an animal type
    it's never seen before?

    Jon

    Comment

    • =?ISO-8859-1?Q?G=F6ran_Andersson?=

      #3
      Re: about using compare with generics

      Tony wrote:
      Hello!
      >
      Below I have a complete working program.with some simple classes one of
      these is a generic class.
      >
      Now If I want to implement functionallity so I can compare animal with each
      other or with other animal
      for example compare a Chicken with a Cow in some way or a Cow with another
      Cow
      >
      How is that done?
      First you have to specify what you want the comparison to do.

      You can already compare the objects:

      if (cow1 == cow2) { ... }

      However, this comparison uses the default reference comparison, so that
      is probably not what you want to do. So, you have to determine what it
      is that you want to do.
      My attempted strategy is to set a constraint on T in such a way that T is
      required to implement the
      CompareTo method that exist in IEnumerable<T>
      So I change the class definition header for the generic class from this
      definition
      public class Farm<T: IEnumerable<Twh ere T : Animal
      to this
      public class Farm<T: IEnumerable<Twh ere T : Animal, IEnumerable<T>
      I then let Cow, Chicken and SuperCow inherit from IEnumarable
      and then implement CompareTo in each class which is Cow, Chicken and
      SuperCow
      >
      I tried this but run into several problems so my strategy was perhaps
      complete
      wrong.
      Making an animal enumerable doesn't seem to make much sense.

      Looping through a cow sound wrong in so many ways... ;)

      Besides, the IEnumerable<Tin terface doesn't contain any CompareTo
      method. Do you mean the IComparable<Tin terface?


      --
      Göran Andersson
      _____
      Göran Anderssons privata hemsida.

      Comment

      • Tony

        #4
        Re: about using compare with generics

        Hello!

        If I want to implement the generic interface IComparable<Tin stead of the
        non-generic how is that done.
        I can change the constraint on T to IComparable<Tin stead of IComparable
        in the class header definition for Farm.

        But how do I write the class definition header for Cow for example now I
        have
        public class Cow : Animal, IComparable

        I can't use any T here!

        //Tony






        "Jon Skeet [C# MVP]" <skeet@pobox.co mskrev i meddelandet
        news:280568ef-bad9-4b5e-a52a-7066ffd1f621@e3 9g2000hsf.googl egroups.com...
        On Jun 19, 1:13 pm, "Tony" <johansson.ande rs...@telia.com wrote:
        Here I have put a constraint on the generic class farm as to
        force T to implement the IComparable interface.
        >
        I just wonder can this be done in a better way because I don't have strong
        types in CompareTo method which is impemented in all classes except the
        abstract
        class ?
        Well, for a start you should think about implementing IComparable<T>
        instead of IComparable.

        But also you really need to think about Marc's questions. How do you
        want a Cow to compare to a Chicken? To another Cow? To an animal type
        it's never seen before?

        Jon


        Comment

        • Jon Skeet [C# MVP]

          #5
          Re: about using compare with generics

          On Jun 19, 3:03 pm, "Tony" <johansson.ande rs...@telia.com wrote:
          But how do I write the class definition header for Cow for example now I
          have
          public class Cow : Animal, IComparable
          >
          I can't use any T here!
          You don't need to:

          public class Cow : Animal, IComparable<Cow >

          Jon

          Comment

          • Marc Gravell

            #6
            Re: about using compare with generics

            Looping through a cow sound wrong in so many ways... ;)

            OK, that made me chuckle. However, I'm more concerned about SuperCow -
            sounds like the marketing strategy for GE livestock...

            Marc

            Comment

            • Marc Gravell

              #7
              Re: about using compare with generics

              The odd thing is; in a funny way there is a sensible OO answer here...
              now, I don't like the idea of a Cow having to know how to compare itself
              to a Duck a Cat and a Chicken, so IComparable[<T>] might not be easy.

              However, lets assume we have a base-class Animal (Cow : Animal, etc); if
              you just have a list of animals (List<Animal>), and an external
              comparer, say:

              Farmer : IComparer<Anima l>

              then you can get your Farmer instance (or whatever) to do the sort:

              List<Animalanim als = ...
              animals.Sort(fa rmer);

              or ditto with Array.Sort<Anim al>(animalArray , farmer);

              Of course, the farmer still needs to have a sensible set of rules for
              comparing each animal.

              If you are comparing based on a property common to all Animal instances
              - their Name, say (do farmers name their animals?), then it is much easier:

              animals.Sort((x ,y) =string.Compare (x.Name, y.Name));

              Marc

              Comment

              Working...