Generic list converter

C

colin

Hi,
I finaly managed to come up with this code after struggling for ages,..
its a way to access my list<T> as if it were a list of list<T2>
it looked a bit unweildly but it seems to work ...
I dont know if there are any better ways of doing this ?
it wouldnt let me simply override things in the main list class.

its just has an interface for a converter to convert the elemnt from one
type to another,
then a generic class wich takes the list class and passes all the enumerator
work directly to it
just intercepting the Current() method to do the conversion.


public interface ElementConverter<To,From>
{
To ConvertElement(From p);
}
public class ListEnum<T,To, From> : IEnumerable<To>, IEnumerator<To>
where T : IList<From>, ElementConverter<To,From>
{
#region IEnumerable Members
public T list;
public IEnumerator<From> enumerator;
public ListEnum(T l)
{
list = l;
}
IEnumerator<To> IEnumerable<To>.GetEnumerator()
{
enumerator = list.GetEnumerator();
return this;
}
#endregion
#region IEnumerator Members
public object Current
{
get { return list.ConvertElement((From)enumerator.Current); }
}
public bool MoveNext()
{
return enumerator.MoveNext();
}
public void Reset()
{
enumerator.Reset();
}
#endregion
#region IDisposable Members
public void Dispose()
{
enumerator.Dispose();
}
#endregion
#region IEnumerable Members
public IEnumerator GetEnumerator()
{
throw new Exception("The method or operation is not
implemented.");
}
#endregion
#region IEnumerator<To> Members
To IEnumerator<To>.Current
{
get { return list.ConvertElement(enumerator.Current); }
}
#endregion
}
public class Point3d
{
Public Vector3 Position;
//...lots of other stuff
}
public class PointList : List<Point3d>,
ElementConverter<Vector3,Point3d>
{
internal IEnumerable<Vector3> VectorList()
{
return (IEnumerable<Vector3>)new ListEnum<PointList, Vector3,
Point3d>(this);
}

#region ElementConverter<Vector3,Point3d> Members

public Vector3 ConvertElement(Point3d p)
{
return p.Position;
}

#endregion
}

basically I store my list of 3d points with all sorts of other information,
wich I need to keep in the same data structure,
but certain functions require a list of vector3 such as creating a
BoundingSphere.
this saves having to create a list of vector3 or try and keep a copy wich
remains up to date.

any comments would be of interest

Colin =^.^=
 
N

Nicholas Paldino [.NET/C# MVP]

colin,

It seems like a lot of work, honestly. Why not just do this:

public static IList<TOutput> ConvertIList<TInput, TOutput>(IList<TInput>
list,
Converter<TInput, TOutput> converter)
{
// Return the new list.
return new List<TOutput>(ConvertIEnumerable(input));
}

private static IEnumerable<TOutput> ConvertIEnumerable<TInput,
TOutput>(IEnumerable<TInput> input,
Converter<TInput, TOutput> converter)
{
// Just convert everything.
foreach (TInput item in input)
{
// Return the output.
yield return converter(item);
}
}

Then, you just use an anonymous method at the call site to handle the
conversion.

If you are using .NET 3.5/C# 3.0 or above, it's even easier as you can
simply select the converted items as you wish (and cast items as well, if
applicable).
 
C

colin

thanks for the very quick reply

yes it does seem like a lot of work wich is why i asked for comments,
hoever basicaly its just wrapping all the ienumerable functions
and passing them all on as is, so most of it is a bit of a no brainer.

ive taken quite a while to get my head round your example,
but it seems like its creating a new list wich is a copy of the converted
elements
wich is not what I was after, unless im mistaken.

the list might be kept around for a while, and as the copy are valuetypes
they could become stale,
I actually did it this way before, just made a copy of the list and tried to
keep it upto date,
but it becomes a bot of a race condition, to make a new copy of the list
every time its accessed is
an overhead id rather avoid. im trying to improve the execution time as it
is.

im using vs express 2005 with .net 2.0, Im wary of uprade unless I need to
as I upgraded to XNA 2.0
then found it was a lot slower so went back to 1.0.

im not sure xna works with vs2008, can I just use .net 3.5 with vs2005 ?
im not sure most people would appreciate the extra 15mb dl for 3.5 though :/

Colin =^.^=



Nicholas Paldino said:
colin,

It seems like a lot of work, honestly. Why not just do this:

public static IList<TOutput> ConvertIList<TInput, TOutput>(IList<TInput>
list,
Converter<TInput, TOutput> converter)
{
// Return the new list.
return new List<TOutput>(ConvertIEnumerable(input));
}

private static IEnumerable<TOutput> ConvertIEnumerable<TInput,
TOutput>(IEnumerable<TInput> input,
Converter<TInput, TOutput> converter)
{
// Just convert everything.
foreach (TInput item in input)
{
// Return the output.
yield return converter(item);
}
}

Then, you just use an anonymous method at the call site to handle the
conversion.

If you are using .NET 3.5/C# 3.0 or above, it's even easier as you can
simply select the converted items as you wish (and cast items as well, if
applicable).


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

colin said:
Hi,
I finaly managed to come up with this code after struggling for ages,..
its a way to access my list<T> as if it were a list of list<T2>
it looked a bit unweildly but it seems to work ...
I dont know if there are any better ways of doing this ?
it wouldnt let me simply override things in the main list class.

its just has an interface for a converter to convert the elemnt from one
type to another,
then a generic class wich takes the list class and passes all the
enumerator work directly to it
just intercepting the Current() method to do the conversion.


public interface ElementConverter<To,From>
{
To ConvertElement(From p);
}
public class ListEnum<T,To, From> : IEnumerable<To>, IEnumerator<To>
where T : IList<From>, ElementConverter<To,From>
{
#region IEnumerable Members
public T list;
public IEnumerator<From> enumerator;
public ListEnum(T l)
{
list = l;
}
IEnumerator<To> IEnumerable<To>.GetEnumerator()
{
enumerator = list.GetEnumerator();
return this;
}
#endregion
#region IEnumerator Members
public object Current
{
get { return list.ConvertElement((From)enumerator.Current); }
}
public bool MoveNext()
{
return enumerator.MoveNext();
}
public void Reset()
{
enumerator.Reset();
}
#endregion
#region IDisposable Members
public void Dispose()
{
enumerator.Dispose();
}
#endregion
#region IEnumerable Members
public IEnumerator GetEnumerator()
{
throw new Exception("The method or operation is not
implemented.");
}
#endregion
#region IEnumerator<To> Members
To IEnumerator<To>.Current
{
get { return list.ConvertElement(enumerator.Current); }
}
#endregion
}
public class Point3d
{
Public Vector3 Position;
//...lots of other stuff
}
public class PointList : List<Point3d>,
ElementConverter<Vector3,Point3d>
{
internal IEnumerable<Vector3> VectorList()
{
return (IEnumerable<Vector3>)new ListEnum<PointList, Vector3,
Point3d>(this);
}

#region ElementConverter<Vector3,Point3d> Members

public Vector3 ConvertElement(Point3d p)
{
return p.Position;
}

#endregion
}

basically I store my list of 3d points with all sorts of other
information,
wich I need to keep in the same data structure,
but certain functions require a list of vector3 such as creating a
BoundingSphere.
this saves having to create a list of vector3 or try and keep a copy wich
remains up to date.

any comments would be of interest

Colin =^.^=
 
C

colin

thanks, i just looked at this again with a fresh cup of realy strong coffee,
and realised I can just use the one function like the one you suggested in
my list class.

internal IEnumerable<Vector3> Vector3IEnumerable()
{
foreach (Point3d p in this)
{
yield return p.Position;
}
}

and just simply pass this member to anything that needs list of vector3's
such as

boundSphere = BoundingSphere.CreateFromPoints(Points.Vector3IEnumerable());

I get confused with the IEnumerable type,
and its relation to IEnumerator,
think i get the conenction now thought I had to do it by
inheriting the interface instead it seems it
can be just a function,
thanks for pointing me in the right direction,


Colin =^.^=



Nicholas Paldino said:
colin,

It seems like a lot of work, honestly. Why not just do this:

public static IList<TOutput> ConvertIList<TInput, TOutput>(IList<TInput>
list,
Converter<TInput, TOutput> converter)
{
// Return the new list.
return new List<TOutput>(ConvertIEnumerable(input));
}

private static IEnumerable<TOutput> ConvertIEnumerable<TInput,
TOutput>(IEnumerable<TInput> input,
Converter<TInput, TOutput> converter)
{
// Just convert everything.
foreach (TInput item in input)
{
// Return the output.
yield return converter(item);
}
}

Then, you just use an anonymous method at the call site to handle the
conversion.

If you are using .NET 3.5/C# 3.0 or above, it's even easier as you can
simply select the converted items as you wish (and cast items as well, if
applicable).


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

colin said:
Hi,
I finaly managed to come up with this code after struggling for ages,..
its a way to access my list<T> as if it were a list of list<T2>
it looked a bit unweildly but it seems to work ...
I dont know if there are any better ways of doing this ?
it wouldnt let me simply override things in the main list class.

its just has an interface for a converter to convert the elemnt from one
type to another,
then a generic class wich takes the list class and passes all the
enumerator work directly to it
just intercepting the Current() method to do the conversion.


public interface ElementConverter<To,From>
{
To ConvertElement(From p);
}
public class ListEnum<T,To, From> : IEnumerable<To>, IEnumerator<To>
where T : IList<From>, ElementConverter<To,From>
{
#region IEnumerable Members
public T list;
public IEnumerator<From> enumerator;
public ListEnum(T l)
{
list = l;
}
IEnumerator<To> IEnumerable<To>.GetEnumerator()
{
enumerator = list.GetEnumerator();
return this;
}
#endregion
#region IEnumerator Members
public object Current
{
get { return list.ConvertElement((From)enumerator.Current); }
}
public bool MoveNext()
{
return enumerator.MoveNext();
}
public void Reset()
{
enumerator.Reset();
}
#endregion
#region IDisposable Members
public void Dispose()
{
enumerator.Dispose();
}
#endregion
#region IEnumerable Members
public IEnumerator GetEnumerator()
{
throw new Exception("The method or operation is not
implemented.");
}
#endregion
#region IEnumerator<To> Members
To IEnumerator<To>.Current
{
get { return list.ConvertElement(enumerator.Current); }
}
#endregion
}
public class Point3d
{
Public Vector3 Position;
//...lots of other stuff
}
public class PointList : List<Point3d>,
ElementConverter<Vector3,Point3d>
{
internal IEnumerable<Vector3> VectorList()
{
return (IEnumerable<Vector3>)new ListEnum<PointList, Vector3,
Point3d>(this);
}

#region ElementConverter<Vector3,Point3d> Members

public Vector3 ConvertElement(Point3d p)
{
return p.Position;
}

#endregion
}

basically I store my list of 3d points with all sorts of other
information,
wich I need to keep in the same data structure,
but certain functions require a list of vector3 such as creating a
BoundingSphere.
this saves having to create a list of vector3 or try and keep a copy wich
remains up to date.

any comments would be of interest

Colin =^.^=
 
C

colin

ok ive got that sussed now, I know how to use an IEnurable as a function
rather than an inherited interface, however I find that just having an
ienumerable type isnt
quite enough for all my needs.

I need to be able to pass my list of point3d to a function as if its a
list/array/ilist of Vector3,
as I need to be able to index into it and to know its Count too ...
is there way to do this thats still as easy ?

The function is passed an array of vector3 directly in other places,
and accepts it as IList<vector3>,
it creates a triangle starting from a specific index,
wich might wrap around the end back to the start.

at the moment I convert the whole Point3d list to a vector3 array.
I could provide all the functionality of the IList class in a wrapper like
I did with the ienumerable, but I missed such an easy aproach before I
was wondering if theres an easy way of doing this too?
maybe what you mentioned about .net 3.0 would make this easy ?

Colin =^.^=
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top