Generics

Nate Bross

Contributor
Joined
Apr 6, 2005
Messages
601
Location
Chicago, IL
Just wondering if I've been missing something all this time.

My main use of Generics is like this
C#:
List<MyUDT> myItems = new List<MyUDT>(50);

foreach(MyUDT i in myItems)
{
    Console.WriteLine(i.ToString());
}

What are some other applications of Generics that you use, or is this the majority of the use?
 
Collections are one of the main use of generics, however they can also be useful for utility functions.

If you wanted to do a simple Min or Max kind of function for example generics can be useful...
C#:
    static class Utils
    {
       public static T Max<T>(T a, T b) where T : IComparable<T>
        {
            return (a.CompareTo(b) > 1 ? a : b);
        }
    }

This can be called like
C#:
string s1 = "Test", s2 = "Example";

string s = Utils.Max(s1, s2);

int i1 = 3434, i2 = 3322342;
int i = Utils.Max(i1, i2);
but only when a valid comparison exists, otherwise a compile time error is generated.
 
Say you have a number of classes (Customer class, TreasuryBond Class, ApplicationForTBond class, etc.) and you want to hold a list of each of the respective instances.

One way to achieve that is to create a class for each class: CustomerStack, TreasuryBondStack, etc... Intuitively (naturally), you see a pattern here, namely, the stack. So, why not create a general (hence, 'generic') class that will support any type and will avail the creation and use of stacks for each type?

That is, create a generic class:

Code:
Public Class Stack(Of [B]T[/B])
    Private _items() As T   ''' dynamic array to hold the times of type T
    Private _cnt As Integer  ''' counter

    '''Now define properties and methods. For instance:
    Public Sub Push(item as T)
         ''add code here
    End Sub

    Public Sub Pop(item as T)
         '' add code here
    End Sub
End Class
 
PD -- that is exactly the type of information I was looking for. I could have been pithy with my question: "What other use of Genrics is there besides Collections?" but this is a programming forum so I felt obligated to post code.

Borix -- For simple implementations couldn't you do ~
C#:
Stack<MyUDT> UDTs = Stack<MyUDT>;

void main()
{
    UDTs.Push(new MyUDT(val1,val2));
}

void ButtonClick(...)
{
    MessageBox.Show(UDTs.Pop().val1Prop);
}
 
A good place to find different uses of generics is the DotNet framework. For instance, there is a generic delegate type...
Code:
public delegate void EventHandler<TEventArgs>(
    Object sender,
    TEventArgs e
) where TEventArgs : EventArgs
This allows you to create an event with any type of EventArgs without declaring a new delegate type.

DotNet doesn't come with a generic EventArgs class, but write your own and you'll be able do add all kinds of events to your object without declaring any new types.
 
Generic EventArgs

DotNet doesn't come with a generic EventArgs class, but write your own and you'll be able do add all kinds of events to your object without declaring any new types.

I've never considered EventArgs to be a good candidate for a generic implementation, since the number and type of event-specific parameters can be so variable. You suggest that you've implemented such a class. Can you show the implementation and how it benefits from using generics?
 
Re: Generic EventArgs

Assume the following sample has two custom event args that are actually useful, the only way to create the events is to declare two delegates and use these in the event declarations...
C#:
    public partial class Form1 : Form
    {
        public delegate void TestEventHandlerOne(object sender, SampleEventArgs e);
        public delegate void TestEventHandlerTwo(object sender, AnotherSampleEventArgs e);

        public event TestEventHandlerOne TestOne;
        public event TestEventHandlerTwo TestTwo;

        public Form1()
        {
            InitializeComponent();
        }
 }

    public class SampleEventArgs : EventArgs
    {}

    public class AnotherSampleEventArgs : EventArgs
    { }

The generic EventHandler<T> however gives the slightly cleaner...
C#:
    public partial class Form1 : Form
    {
       public event EventHandler<SampleEventArgs> TestOne;
       public event EventHandler<AnotherSampleEventArgs> TestTwo;

        public Form1()
        {
            InitializeComponent();
        }
 }

    public class SampleEventArgs : EventArgs
    {}

    public class AnotherSampleEventArgs : EventArgs
    { }
 
Generic EventArgs

I understand the usefulness of the generic EventHandler delegate. However, marble_eater suggested creating a generic EventArgs class, and I am struggling to see how generics could be useful here.

What I end up having to do is basically what you've described in your post with SampleEventArgs and AnotherSampleEventArgs. If there were a way to reduce these into a common generic class, I would be very interested. I just don't see how this could be done without having to impose limitations on the parameters passed within the EventArgs object.
 
Re: Generic EventArgs

There certainly won't be a generic EventArgs class that can handle all situations, but a small library will cover most situations.

C# Code[HorizontalRule]magic hidden text[/HorizontalRule]public partial class Form1:Form
{
····public Form1() {
········InitializeComponent();
········this.label1.TextChanged += new EventHandler(label1_TextChanged);
····}

····void label1_TextChanged(object sender, EventArgs e) {
········// Create a purpose-typed event args object without declaring a new type.
········ValueChangedEventArgs<Label, String> args = new ValueChangedEventArgs<Label, string>();
········args.Target = label1;
········args.OldValue = chachedLabelValue;
········args.NewValue = label1.Text;

········LabelTextChanged(this, args);
····}

····// Create an event without declaring a new delegate type.
····public event EventHandler<ValueChangedEventArgs<Label, string>> LabelTextChanged;
}


// Here we have some event args classes. The important thing
// here is that these can be reused for any DotNet type.
public class TargetEventArgs<T>:EventArgs
{
····private T target;
····public T Target { get { return target; } set { target = value; } }

}
public class ValueChangedEventArgs<TTarget, TValueType>:TargetEventArgs<TTarget>
{
····private TValueType oldvalue,newvalue;

····public TValueType OldValue { get { return oldvalue; } set { oldvalue = value; } }
····public TValueType NewValue { get { return newvalue; } set { newvalue = value; } }
}
[HorizontalRule]Why are you quoting me?[/HorizontalRule]
 
Which do you think is better? And more importantly, why?

Obviously this first approach is good for simple implimentations while the second lends itself to greater flexibility.

What are some reasons you think of that would push a "simple implimentaiton" to a more complex one that might require the added flexibility?

C#:
..BOL..
public class MyClass
{
...
}

..DAL..
public List<MyClass> GetMyClassObjects(String SearchParm)
{
.....
}

..presentation..
DAL myDAL = new DAL();
List<MyClass> myList = myDAL.GetMyClassObjects("New");
DataGrid.Datasource = myList;
DataGrid.DataBind();

Or something like this

C#:
..BOL..
public class MyClass
{
...
}
public class MyClassList : List<MyClassList>
{
...
}

..DAL..
public MyClassList GetMyClassObjects(String SearchParm)
{
...
}

..presentation..
DAL myDAL = new DAL();
MyClassList myList = myDAL.GetMyClassObjects("New");
DataGrid.Datasource = myList;
DataGrid.DataBind();
 
I've used both - a simple return type of List<T> and a class that derives from List<T>.

Here's how I decide (if-based, because I'm a programmer :) )

If the list is "internal" only - just a quick return type so I can iterate over the list, use the simple List<T> return type.
Else create a class.

More often than not, once I have created the class I find a reason to add a method or two.

-ner
 
Thats exactly the type of response I was looking for, thanks!

I had been using a similar approach; so I feel good now that at least one other person shares my logic!
 
Return interfaces where possible.

I always try to return interfaces where possible, so in this example I would return IList<T>. This then allows me to change what object I actually return without needing to redefine the function. I often start with List<T> then change to a custom derived class, or ReadOnlyCollection<T>, depending on requirements.
 
So in my example above, you would change to something like this?

My undestanding of Interfaces is very basic......
C#:
..BOL..
public class MyClass
{
...
}
public class MyClassList : IList<MyClass>
{
...
}

..DAL..
public IList<MyClass> GetMyClassObjects(String SearchParm)
{
...
...
return new MyClassList(...);
}

..presentation..
DAL myDAL = new DAL();
MyClassList myList = myDAL.GetMyClassObjects("New");
DataGrid.Datasource = myList;
DataGrid.DataBind();
 
Back
Top