When should or shouldn't I use type constraints?
I've got a base class:

    public abstract class StuffBase
    {
        public abstract void DoSomething();
    }

And two derived classes

    public class Stuff1 : StuffBase
    {
        public void DoSomething()
        {
            Console.WriteLine("Stuff 1 did something cool!");
        }
        public Stuff1()
        {
            Console.WriteLine("New stuff 1 reporting for duty!");
        }
    }

    public class Stuff2 : StuffBase
    {
        public void DoSomething()
        {
            Console.WriteLine("Stuff 2 did something cool!");
        }
        public Stuff1()
        {
            Console.WriteLine("New stuff 2 reporting for duty!");
        }
    }

Okay, now say I've got a list of items:

    var items = new List<StuffBase>();
    items.Add(new Stuff1());
    items.Add(new Stuff2());
    
and I want them all to call their DoSomething() method. I could expect to just iterate the list and call their DoSomething() method, so let's say I've got a method to do that called AllDoSomething() that just iterates over the list and does the job:

    public static void AllDoSomething(List<StuffBase> items)
    {
        items.ForEach(i => i.DoSomething());
    }

What is the practical difference of the following method?

    public static void AllDoSomething<T>(List<T> items) where T: StuffBase
    {
        items.ForEach(i => i.DoSomething());
    }

Both methods appear in real terms, although being syntactically different, to be doing the same thing.

Are they just different ways of doing the same thing?  I understand generics and type constraints but can't see why I would use one way over the other in this instance.
When should or shouldn't I use type constraints?
===

I've got a base class:

    public abstract class StuffBase
    {
        public abstract void DoSomething();
    }

And two derived classes

    public class Stuff1 : StuffBase
    {
        public void DoSomething()
        {
            Console.WriteLine("Stuff 1 did something cool!");
        }
        public Stuff1()
        {
            Console.WriteLine("New stuff 1 reporting for duty!");
        }
    }

    public class Stuff2 : StuffBase
    {
        public void DoSomething()
        {
            Console.WriteLine("Stuff 2 did something cool!");
        }
        public Stuff1()
        {
            Console.WriteLine("New stuff 2 reporting for duty!");
        }
    }

Okay, now say I've got a list of items:

    var items = new List<StuffBase>();
    items.Add(new Stuff1());
    items.Add(new Stuff2());
    
and I want them all to call their DoSomething() method. I could expect to just iterate the list and call their DoSomething() method, so let's say I've got a method to do that called AllDoSomething() that just iterates over the list and does the job:

    public static void AllDoSomething(List<StuffBase> items)
    {
        items.ForEach(i => i.DoSomething());
    }

What is the practical difference of the following method?

    public static void AllDoSomething<T>(List<T> items) where T: StuffBase
    {
        items.ForEach(i => i.DoSomething());
    }

Both methods appear in real terms, although being syntactically different, to be doing the same thing.

Are they just different ways of doing the same thing?  I understand generics and type constraints but can't see why I would use one way over the other in this instance.