Strongly-typed CopyTo() implementation

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I have a collectiond derived from NameObjectCollectionBase. FxCop is
complaining that I need to implement a strongly typed CopyTo(MyObjectType,
int)

How do I do this? I can't seem to find any implementations of CopyTo() that
don't rely on Array.Copy or some other internal .NET method. Unfortunately,
there's nothing I can find that will work for a NameObjectCollectionBase
derived class. I can't find any implementations of CopyTo() for
NameObjectCollectionBase derived classes out on google either.

The documentations doesn't really explain how CopyTo() is supposed to
function. The one thing that appears missing is an explanation of what
you're supposed to do if the index passed in is mid-way into the array. Do
you shift all the items out to make room or do you overwrite existing items?
I presume you shift them out.

I tried seeing how .NET implements it in similar collections using
Reflector. Unfortunately, all the implementations appear to be written in
unmanaged code, so I can't see how they're implemented.

Can anyone help me on this? I need to do it, I presume, for both the Keys
and the Values members. Also, there's no Insert() functionality in
NameObjectCollectionBase, so I'm not sure how to shift the elements out.

Thanks.

Pete Davis
 
Hi Pete, Why would you believe that you couldn't/shouldn't use an internal,
Object-typed method in the implementation of your strong-typed CopyTo
method? I believe all FXCop wants is for you to add an overload of CopyTo
that specifies the array type to copy to. In your case this would be
DictionaryEntry, or some custom class that specified a string key and object
value.

BTW, the only CopyTo behaviour I've ever seen overwrites any items in the
target array, and makes no attempt to re-create a new array if the target
array isn't big enough, however that may not always be the case.

Richard
 
The underlying implementation of CopyTo() in NameObjectCollectionBase is
private, so I can't call down to it. There's no implementation in the
underlying base class to handle this. The keys and values are collections
(not arrays) that also don't support CopyTo(). So how do I write a
CopyTo()????

That's my question. The destination array can't be pre-allocated to be large
enough since ever value must have a unique key (I believe. Maybe I'm wrong
on this. I'll check). So I'd have to use Add() to add new values (since
there's no Insert). But if I'm doing a CopyTo() mid-array, I guess I'd use
the indexer to overwrite, according to what you're saying. Is that correct?

Pete
 
--
C#, .NET and Complex Adaptive Systems:
http://blogs.geekdojo.net/Richard
The underlying implementation of CopyTo() in NameObjectCollectionBase is
private, so I can't call down to it. There's no implementation in the
underlying base class to handle this.

The implementation is not visible if you have a variable of type
NameObjectCollectionBase, but NameObjectCollectionBase implements
ICollection. Simply cast your reference of NameObjectCollectionBase to
ICollection and you'll have a base CopyTo implementation that you can use to
implement your strongly-typed CopyTo.

I.e. (warning: air code, extra work may be required)

classs MyNameCollection : NameObjectCollectionBase
{
// this should shuttup FXCop!:
public void CopyTo(MyObjectType[] array, int index)
{
((ICollection)this).CopyTo(array, index);
}

Now you just let CopyTo deal with the specifics of the copying. Since the
array reference is passed in by value, there's no way to "swap out" the
original array that's being passed in, so you shouldn't worry about whether
the target array is large enough. If it isn't, CopyTo should throw an
ArgumentException. It's the responsibility of the caller to make sure the
array is large enough.

If you want a CopyTo-style method that does 'grow' the array as needed, you
should create a different method with this signature (or have the user pass
in an ArrayList):

public void InflatableCopyTo(ref MyObjectType[] array, int index)
{
// code to grow array here.
}

Since you can't 'grow' an array, you have to re-allocate and swap out the
old one for the new one, you'll need a ref or out on the parameter to tell
the caller you will (potentially) be changing the array.

HTH,
Richard
 
Back
Top