简体   繁体   中英

C# generics question

I'm trying to complete a practice question from a book on generics but the question doesn't make sense to me. Here it goes.

Create two classes with identical functionality. Use generics for the first class, and cast the second class to Object types. Create a for loop that uses class and the Object based class to determine which performs better.

I'm not sure what it means by casting to Object types. Here is my code so far

   //Generic
    class Person<T> {

        T var1;

        public Person(T yer) {
            var1 = yer;
        }

        public T Value { get { return var1; } }
    }

    //Normal class
    class Human {

        int var1;

        public Human(int yer) {
            var1 = yer;
        }

        public int Value { get { return var1; } }
    }

My main program running the loops

for (int i = 0; i < 1000000; i++) {
                Person<int> me = new Person<int>(1);
                int hey = me.Value;
            }

            for (int i = 0; i < 1000000; i++) {
                Human per = new Human(1);
                object her = (object)per.Value;
            }

I don't know if Im doing this right. Help please :-)

I think that the question is asking you to create a collection class, and insert instances of your class into that.

Eg,

Generics version:

List<Human> myList = new List<Human>();
Human h = new Human();
myList.Add(h);

Object version:

ArrayList myObjectList = new ArrayList();
Human h = new Human();
myObjectList.Add((object)h));

I haven't checked whether that compiles, and have to run now.

I think the question is for looping over a collection of your classes.

Generic

List<Person> pList = new List<Person>();
for(int i = 0; i<1000; ++i)
    pList.Add(new Person(30));

StopWatch sw = new StopWatch();
sw.start();
int sum = 0;
foreach(Person p in pList)
    sum += p.Value;
sw.Stop();

Object

ArrayList hList = new ArrayList;
for(int i = 0; i<1000; ++i)
    hList.Add(new Human(30));

StopWatch sw = new StopWatch();
sw.start();
int sum = 0;
foreach(Object h in hList)
    sum += ((Human)h).Value;
sw.Stop();

What you are being asked to do is use the Object inside your class, so Person<> is perfect. What you need to do is change Human so that Var1 is an object. Then, wherever you use var1 cast it to or from an int:

class Human 
{        
     object var1;
     public Human(int yer) 
     {            
          var1 = (object) yer;        
     }
     public int Value 
     { 
         get { return (int) var1;     }
     }    
}

The confusion come from the fact in this example, var1 really can't be anything besides an int, so it's really not a good candidate for generics, and in production should be written as you originally wrote Human. But as I wrote it, it's OK for this exercise.

I think you've got it right except for the for loops. An int is an object type so replace

object her = (object)per.Value;

with

int her = per.Value;

The other thing you're missing is some performance counters. Have a look at the Timer class to see what kinds of things you can do to see which is a better performer.

I'm not sure, but it sounds to me like a question that is trying to test out your knowledge of boxing and unboxing rules.

int i = 123; object o = (object)i; // boxing

The object o can then be unboxed and assigned to integer variable i:

o = 123; i = (int)o; // unboxing

If an object gets boxed and unboxed it is slower as a new object gets created.

Yes, you are doing it right. There isn't much you can do with pure Object instances as most operators don't work on them. There are four public methods defined: Equals, GetHashCode, GetType and ToString. I guess you could fiddle with Equals and see if that makes any difference.

Well if I am doing it right, then according to my counters (DateTime.Now.Ticks) then I can't see any difference in performance at all.

If I take endian's approach then I can see where the performance hit is.

Lets hope my exam questions are a little clearer.

Thanks everyone.

I know this is a late addition to this question but I used this code exactly and got it to work by using DateTime.Now.Ticks just by updating the following:

        DateTime t = DateTime.Now;
        for (int i = 0; i < 1000000; i++)
        {
            Person<int> me = new Person<int>(1);
            int hey = me.Value;
        }
        long a = DateTime.Now.Ticks - t.Ticks;
        TimeSpan A = new TimeSpan(a);


        for (int i = 0; i < 1000000; i++)
        {
            Human per = new Human(1);
            object her = (object)per.Value;
        }

        long b = DateTime.Now.Ticks - t.Ticks;
        TimeSpan B = new TimeSpan(b);

        Console.WriteLine(A.ToString());
        Console.WriteLine(B.ToString());
        Console.ReadLine();

There is a big difference in performance, as generics is about twice as fast.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM