Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / C# / March 2008

Tip: Looking for answers? Try searching our database.

Deriving from IList question

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Bart - 26 Mar 2008 00:40 GMT
Hi all,

I have created a class which derives fron IList.

It looks like this:

public class Signals<Signal>: IList<Signal>

But I don't know how to impement the next section.

#region IEnumerable Members

System.Collections.IEnumerator
System.Collections.IEnumerable.GetEnumerator()
{
  throw new NotImplementedException();
}

#endregion

How should I implent this. Can someone give me an example ?

Thanks in advance,

Bart
Peter Duniho - 26 Mar 2008 00:48 GMT
> [...]
> But I don't know how to impement the next section.
[quoted text clipped - 6 lines]
>
> How should I implent this. Can someone give me an example ?

You probably are looking for something like this:
http://msdn2.microsoft.com/en-us/library/dscyy5s0.aspx

It documents implementation of iterators in C#.

Pete
Bart - 26 Mar 2008 01:02 GMT
Hi Peter,

Thanks for your quick answer.

In my class I create a private list. Can I just return _list.GetEnumerator()

Sorry for the probably dumb question :(

Bart

>> [...]
>> But I don't know how to impement the next section.
[quoted text clipped - 13 lines]
>
> Pete
Peter Duniho - 26 Mar 2008 01:25 GMT
> In my class I create a private list. Can I just return  
> _list.GetEnumerator()
>
> Sorry for the probably dumb question :(

No need to apologize.  There are dumb ways to ask a question, but there  
are no dumb questions.

As for whether you can delegate the retrieval of an enumerator to a  
contained IList implementation, sure.  That's a perfectly acceptable  
implementation, especially if your own class is acting as a collection but  
is essentially delegating all of the other collection behaviors to that  
same IList.

Pete
Marc Gravell - 26 Mar 2008 08:21 GMT
For the record - alternative approaches might be to inherit from
Collection<T> or List<T> (the first offers more extension points) and
just add the functionality you need... something like below. This then
given you standard IList/IList<T> etc for free:

public sealed class Signals : Collection<Signal>
{
   protected override void InsertItem(int index, Signal item)
   {
       CheckValid(item);
       base.InsertItem(index, item);
   }
   protected override void SetItem(int index, Signal item)
   {
       CheckValid(item);
       base.SetItem(index, item);
   }
   void CheckValid(Signal item)
   {
       if (item.Foo < 0) throw new InvalidOperationException("Foo
must be non-negative");
   }
}
Bart - 26 Mar 2008 18:38 GMT
Another question about this.

I did try to derive from List<T> and Collection<T> but I was not able to
override for example the Add method. I am happy the way it is implemented it
right now.

But one thing I can't accomplish and could need some more help with it. In
the method add I want to show a messagebox with the signal name like this:

public void Add(Signal item)
{
   MessageBox.Show(item.Name);
   _list.Add(item);
}

But I can't compile this and I don't understand why item is not of type
Signal. Even casting it to a Signal didn't do the trick.

So can someone show me how I could to this.

Thanks again,

Bart
Peter Duniho - 26 Mar 2008 18:59 GMT
> [...]
> public void Add(Signal item)
[quoted text clipped - 5 lines]
> But I can't compile this and I don't understand why item is not of type
> Signal. Even casting it to a Signal didn't do the trick.

Without a more complete code sample and the exact text of the compiler  
error, it's hard to say what might be going wrong.

However, if you're inheriting List<T> directly, I'm not clear on why you  
still have a "_list" member.  By inheriting List<T>, your own class  
"becomes" the list.  You shouldn't need a private "_list" to store the  
data at that point.

Pete
Peter Duniho - 26 Mar 2008 19:00 GMT
> [...]
> But I can't compile this and I don't understand why item is not of type
> Signal. Even casting it to a Signal didn't do the trick.

Forgot to add...

Note also that the Add() method isn't virtual, so you can't override it  
anyway.  If you have the need to provide your own behavior, it may in fact  
be better to do this the way you were before, with composition rather than  
inheritance.

Pete
Bart - 27 Mar 2008 00:22 GMT
> Note also that the Add() method isn't virtual, so you can't override it
> anyway.  If you have the need to provide your own behavior, it may in fact
> be better to do this the way you were before, with composition rather than
> inheritance.

That's exactly the reason why I choose for composition. Anyway the
constructor for my Signals get a reference to a validator. This validator
should validate the Signal item.

Sore here is the most important peace of the code I hope you could help me
out here. Thanks again.

public class SignalValidator
{
   public bool Validate(Signal signal)
   {
       return true; // True for the moment !!!
   }
}
-------------------------------------------------------
public class Signal
{
   private int _number;
   private string _name;
   private string _comment;

   public Signal()
   {
   }

   public Signal(int Number, string Name, string Comment)
   {
       _number = Number;
       _name = Name;
       _comment = Comment;
   }

   public int Number
   {
       get {return _number ;}
       set { _number = value;}
   }

   public string Name
   {
       get{ return _name;}
       set{ _name = value;}
   }

   public string Comment
   {
       get{ return _comment; }
       set{ _comment = value; }
   }
}
--------------------------------------------------------------------
public class Signals<Signal>: IList<Signal>
{
   private List<Signal> _list = new List<Signal>();

   public Signals(SignalValidator Validator)
   {
       _validator = Validator;
   }

   public void Add(Signal item)
   {
       if(!_validater.Validate(item))
       {
          Trow new exception();
       }
       else
       {
          _list.Add(item);
       }
   }
}

Regards,

Bart
Bart - 27 Mar 2008 00:28 GMT
Sorry forgot the compiler messages:

Error 1 The best overloaded method match for
'SignalList.SignalValidator.Validate(SignalList.Signal)' has some invalid
arguments D:\Users\Bart\Visual Studio
2008\Projects\SignalList\SignalList\Signals.cs 65 13 SignalList

Error 2 Argument '1': cannot convert from 'Signal' to 'SignalList.Signal'
D:\Users\Bart\Visual Studio 2008\Projects\SignalList\SignalList\Signals.cs
65 33 SignalList

Bart
Peter Duniho - 27 Mar 2008 00:50 GMT
>> Note also that the Add() method isn't virtual, so you can't override it
>> anyway.  If you have the need to provide your own behavior, it may in  
[quoted text clipped - 10 lines]
> me
> out here. Thanks again.

Well, ignoring for a moment at least three other errors in your code that  
I see, I think the issue you're running into is here:

> [...]
>     public void Add(Signal item)
[quoted text clipped - 9 lines]
>     }
> }

Your SignalValidator class requires that you pass it a Signal.  However,  
your Signals<Signal> class is actually a generic class, with the type  
parameter named "Signal" not constrained to anything.  So when you try to  
call "_validater.Validate(item) [sic]", the compiler complains because it  
has no idea at the moment that it's compiling that code that "item" is of  
type "Signal".  It has the type of the generic type parameter _named_  
"Signal" but that's the name of the type parameter, not the class actually  
being used.

I suspect that what you really want is to declare your Signals class like  
this:

    public class Signals : IList<Signal>

If you do that, I think the code will compile (after you fix the other  
errors).

Alternative solutions would include constraining the type parameter:

    public class Signals<T> : IList<T> where T : Signal

Or making the SignalValidator class generic as well:

    public class SignalValidator<T> { ... }

    public class Signals<T> : IList<T>
    {
        private SignalValidator<T> _validator;
        private List<T> _list = new List<T>();

        public Signals(SignalValidator<T> Validator)
        {
            _validator = Validator;
        }

        public void Add(T item)
        {
            if(!_validator.Validate(item))
            {
               throw new Exception();
            }
            else
            {
               _list.Add(item);
            }
        }
    }

Of course, in this last option, it begs the question as to what the  
generic SignalValidator<T> might do.  Since it wouldn't necessarily know  
anything about the generic type parameter (unless you constrained its type  
parameter to Signal, when you'd then have to do for the Signals class  
anyway, obviating the need to make SignalValidator generic in the first  
place), you would need to provide some sort of validating method for the  
class.  Assuming all the class does is call the validating method, you  
could do away with the SignalValidator class altogether and just declare a  
validating method delegate type to be passed to the Signals class instead:

    public delegate bool SignalValidator<T>(T t);

    public class Signals<T> : IList<T>
    {
        private SignalValidator<T> _validator;
        private List<T> _list = new List<T>();

        public Signals(SignalValidator<T> Validator)
        {
            _validator = Validator;
        }

        public void Add(T item)
        {
            if(!_validator(item))
            {
               throw new Exception();
            }
            else
            {
               _list.Add(item);
            }
        }
    }

Then when you instantiate a Signals<T>, you'd simply pass in a method to  
be used for validation rather than a whole class.

Anyway, as I said...I think what you really want is the first suggestion  
above.  But any of the above should work better than what you've got right  
now.

Pete
Bart - 27 Mar 2008 18:22 GMT
Hi Peter,

Thanks for your answers so far. I must admit that I have to chew on this.
But when you don't mind I like to come back on it.

Bart
Peter Duniho - 27 Mar 2008 19:08 GMT
> Thanks for your answers so far. I must admit that I have to chew on this.
> But when you don't mind I like to come back on it.

Of course.  No problem.  I think the key thing you need to understand is  
that if you declare a class with the syntax "class  
MyClassName<SomeIdentifier>", the "SomeIdentifier" becomes the type  
parameter, and does not reference some other existing type.

It's sort of like declaring a method like this:

    public MyClass { }
    public MyOtherClass { }

    void MyMethod(MyOtherClass MyClass)
    {
    }

In this case, the variable "MyClass" is of type "MyOtherClass", even  
though you've used a name that already exists as a type name.

So when you wrote "class Signals<Signal>", you aren't referencing the  
existing "Signal" class.  You're declaring a generic class, one that has a  
type parameter named "Signal" and which other than sharing the name has  
nothing to do with the actual "Signal" class.

Unless you actually meant to _declare_ a generic class (as opposed to  
simply _using_ an existing generic class or, in this case, interface), you  
really just want to declare your class as "class Signals" instead of  
"class Signals<Signal>".

I made a guess that this is in fact what you want, thus I presented that  
as my first suggestion.  I apologize if the remainder of the discussion  
was just confusing the issue.

Pete
Bart - 28 Mar 2008 01:03 GMT
Hi Peter,

> So when you wrote "class Signals<Signal>", you aren't referencing the
> existing "Signal" class.  You're declaring a generic class, one that has a
> type parameter named "Signal" and which other than sharing the name has
> nothing to do with the actual "Signal" class.

I think you are exactly right. I didn't understand exactly what I wrote. I
thought I was referencing the Signal object. Although you made me clear that
this is not right I am still having some trouble to grasp the hole generic
thing. The reason for this is that when I write Signals.Add(new Signal(10,
"bla", bla")); I somehow think I get a reference to this Signal inside my
Signals class. But I guess that's because of my Delphi background. So I have
to do some more reading about this.

> I made a guess that this is in fact what you want, thus I presented that
> as my first suggestion.  I apologize if the remainder of the discussion
> was just confusing the issue.

No peter you didn't confuse me. Instead you opened my eyes. At the moment I
am thinking about redesigning my classes. My Signals class is a special
class that only needs to store Signals and syould be capable of validating
them. So at the moment I think that Signals only need to be composed with a
private List<Signal>. But I need to find out how to make iteratable so that
i can write foreach(Signal s in Signal){........}.

Peter I hope that I don't give you the feeling that I that this issue
doesn't have my attention because of my late responsens to your posts. But
since you are so kind to put so much effort and time in it to help me, I
feel obligated to you that I have have to tell that my mom had a hart atack
and she in the hospital right now. Luckilly she made it and she quite
allright . So that is the reason for my low response to you but as you can
understand that consumes a lot of time and energy right now.

Thanks again,

Bart
Peter Duniho - 28 Mar 2008 02:42 GMT
> I think you are exactly right. I didn't understand exactly what I  
> wrote.  I
[quoted text clipped - 6 lines]
> "bla", bla")); I somehow think I get a reference to this Signal inside my
> Signals class.

I'm not sure what you mean here, as you're implying that you don't get a  
reference to the new Signal instance inside your Signals class.  But you  
do.  "new Signal(10, "bla", "bla")" creates (assuming that's a valid  
constructor) a new instance of the Signal class.  The reference to that  
instance is passed to the Add() method.  For the Add() method you've  
posted here, the reference is first passed to your validator, and then if  
it passes, it's added to the list.

At that point, the reference to the new Signal instance is now stored in  
the list.

> But I guess that's because of my Delphi background. So I have
> to do some more reading about this.

As far as I can tell, you haven't misinterpreted what that line of code  
does.  Is there something that makes you think that you have?

> No peter you didn't confuse me. Instead you opened my eyes. At the  
> moment I
[quoted text clipped - 6 lines]
> that
> i can write foreach(Signal s in Signal){........}.

Well, by declaring the class as implementing IList<Signal>, you've  
indicated that your class will implement IEnumerable<Signal> and  
IEnumerable.  Those in turn indicate that your class will implement the  
method GetEnumerator() returning an IEnumerator<Signal>.

So, to complete your implementation of IList<Signal>, one thing you'll  
need to do is create the method GetEnumerator(), returning an  
IEnumerator<Signal>.  One way to do this is to write the method as an  
iterator.  But an easier way is to just call List<Signal>.GetEnumerator(),  
using the List<Signal> instance in your Signals class.

This is, if I recall correctly, where this thread started.  :)

> Peter I hope that I don't give you the feeling that I that this issue
> doesn't have my attention because of my late responsens to your posts.  
> [...]

You don't at all give me that feeling.  I'm sorry for your personal  
troubles, but rest assured: it's of no concern to me how much attention  
you are or are not focusing on this particular question.  I'm happy to  
answer the questions you might have as they come up, when they come up, as  
best as I can, if I can.  It doesn't matter to me if it takes you hours,  
days, weeks, or longer for you to return to the question to follow up on a  
previous answer (though, of course, the longer you take, the greater the  
chance I may write something that ignores some information that was  
already in the thread...but as long as you don't mind that, it's not a  
problem).

Pete
Mel - 26 Mar 2008 19:13 GMT
Changed it to
   public new void Add(Signal item)
   {
   }

> Another question about this.
>
[quoted text clipped - 19 lines]
>
> Bart
Peter Duniho - 26 Mar 2008 23:52 GMT
> Changed it to
>     public new void Add(Signal item)
>     {
>     }

Noting that that does _NOT_ override the method.  It hides it.  If and  
when the class is used as the inherited List<Signal> class, the original  
Add() method will be called instead.

IMHO, it's really a poor choice to hide a method like this.  The code  
becomes overly fragile when you do that, and it can lead to severe  
headaches later on.

Pete

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.