Jump to content

  • Log In with Google      Sign In   
  • Create Account


Generic method with objects


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
6 replies to this topic

#1 fafase   Members   -  Reputation: 352

Like
0Likes
Like

Posted 28 August 2012 - 12:36 AM

Hey,

Being not totally advanced yet with C# I am trying to develop a function that would instantiate a list of object.

[source lang="java"]public static List<T> CreateObjLeft<T>(T type) { List<T> temp = new List<T>(); for (int i = 0; i < 10; i++) { temp.Add(type); } return temp;}[/source]
This is somehow working, I get my 10 objects but I need to access each instance. I created a default constructor for the object, but at the moment all objects in the list have the same attributes and I need to access the position (it is for a game) so that they do not all show on top of each other.

I am trying to create a pattern of object (circle, triangle...) and I would like to be able to use the same generic function for whatever object I want to create (pretty mush the principle of generic methods...).

I have also tried to cast the object inside as such:

[source lang="csharp"]if (type is Asteroid) { ((Asteroid)type).position = new Vector2(0,0); }[/source]

But then I get an error Cannot convert type T to my own class. Or trying to access the object of the list in the same fashion:


[source lang="csharp"]if (temp is Asteroid) { ((Asteroid)temp)[0].position = new Vector2(0,0); }[/source]
Error 5 Cannot convert type 'System.Collections.Generic.List<T>' to 'Tutorial.Asteroid'

Does anyone has a solution in mind? Or I thought of trying to add my custom object type to Generic.List<T> but could not really get it...

Thanks

Sponsor:

#2 lwm   Members   -  Reputation: 1385

Like
4Likes
Like

Posted 28 August 2012 - 01:24 AM

Just to make sure I understood correctly: You want the method to instantiate multiple objects, initialize them all differently and put them in a list?

Assuming that T is a reference type, the first method you provided receives a reference to an object of type T and adds the same reference to the list 10 times. Also, in modern C#, there is really no reason to use the non-generic versions of the built-in collections.

static void Main(string[] args)
{
	Action<Asteroid, int, int> initCircle = (obj, i, amount) => {
		float a = ((float)i / (float)amount) * MathHelper.TwoPi;
		float x = (float)Math.Sin(a);
		float y = (float)Math.Cos(a);
		obj.position = new Vector2(x, y);
	};
	var list = CreateMultipleObjects<Asteroid>(10, initCircle);
}
public static List<T> CreateMultipleObjects<T>(int amount, Action<T, int, int> initialize) where T : class, new()
{
	List<T> temp = new List<T>();
	for (int i = 0; i < amount; i++)
	{
		T obj = new T();
		initialize(obj, i, amount);
		temp.Add(obj);
	}
	return temp;
}

Edited by lwm, 28 August 2012 - 01:25 AM.

current project: Roa


#3 fafase   Members   -  Reputation: 352

Like
0Likes
Like

Posted 28 August 2012 - 01:58 AM

Thanks a hell of a bunch!!! Unfortunately I can only upvote once...

Well, that did the trick now I need to review all that and understand how and why it works. I have never heard of Action and delegates (still discovering C#).

Also,I was scared you led me somewhere lost as all my object were on the same spot at first but then I realized you just assign the same position in initCircle (I guess you forgot to use i).

Again thanks for that.

#4 lwm   Members   -  Reputation: 1385

Like
2Likes
Like

Posted 28 August 2012 - 02:12 AM

Thanks a hell of a bunch!!! Unfortunately I can only upvote once...

Well, that did the trick now I need to review all that and understand how and why it works. I have never heard of Action and delegates (still discovering C#).

Also,I was scared you led me somewhere lost as all my object were on the same spot at first but then I realized you just assign the same position in initCircle (I guess you forgot to use i).

Again thanks for that.


I'm glad I could help Posted Image
I used the i in initCircle to calculate a, but you probably have to scale up the vector in order to see the circle.
obj.position = new Vector2(x, y) * 100;
should produce a circle with radius 100.

Edited by lwm, 28 August 2012 - 02:14 AM.

current project: Roa


#5 fafase   Members   -  Reputation: 352

Like
0Likes
Like

Posted 28 August 2012 - 02:30 AM

One last thing,

[source lang="csharp"]Action<Asteroid, int, int> initCircle = (obj, i, amount) => { float a = ((float)i / (float)amount) * MathHelper.TwoPi; float x = (float)Math.Sin(a); float y = (float)Math.Cos(a); obj.position = new Vector2(x, y); };[/source]
Action<Asteroid, int, int> this declaration will not work if I pass another object type to it, I tried replacing Asteroid with T but no go. The idea would be that if I pass an object of type SpaceShip, it would create s circle of them. Do I need to create a second Action with the SpaceShip or could I alter the existing one so that anything passed would do.

So I can call
[source lang="csharp"]asteroids.AddRange(PatternAst.CreateMultipleObjects<Asteroid>(10, PatternAst.initCircle));asteroids.AddRange(PatternAst.CreateMultipleObjects<SpaceShip>(10, PatternAst.initCircle));[/source]
(Obvisouly not at the same time) adn I would get a circle of asteroid and a circle of spaceship.

I would guess there is a way to do so.

Sorry for so many questions.

#6 lwm   Members   -  Reputation: 1385

Like
2Likes
Like

Posted 28 August 2012 - 02:54 AM

The most straight-forward thing would probably be to make all classes that you want to initialize that way implement a common interface, like "IHasPosition".
Or, if you want to make the your PatternAst class even more generic, you can provide a setter action to the method.

public interface IHasPosition
{
	Vector2 Position { get; set; }
}
public class Asteroid : IHasPosition
{
	public Vector2 Position { get; set; }
}
public class Asteroid2
{
	public Vector2 Position { get; set; }
}
public static class PatternAst
{
	static void Main(string[] args)
	{
		// Use the fact, that Asteroid implements IHasPosition
		var list1 = CreateCircle<Asteroid>(10, new Vector2(0, 0), 100);
		// Asteroid2 does not implement IHasPosition, use second method with setter action
		var list2 = CreateCircle<Asteroid2>(10, new Vector2(0, 0), 100, (obj, pos) => { obj.Position = pos; });
	}
	private static Vector2 PositionInCircle(int i, int amount, Vector2 center, float radius)
	{
		float a = ((float)i / (float)amount) * MathHelper.TwoPi;
		float x = (float)Math.Sin(a);
		float y = (float)Math.Cos(a);
		return center + new Vector2(x, y) * radius;
	}
	public static List<T> CreateCircle<T>(int amount, Vector2 center, float radius) where T : class, IHasPosition, new()
	{
		var list = CreateMultipleObjects<T>(amount);
		for (int i = 0; i < list.Count; i++)
		{
			list[i].Position = PositionInCircle(i, list.Count, center, radius);
		}
		return list;
	}
	public static List<T> CreateCircle<T>(int amount, Vector2 center, float radius, Action<T, Vector2> positionSetter) where T : class, new()
	{
		var list = CreateMultipleObjects<T>(amount);
		for (int i = 0; i < list.Count; i++)
		{
			var pos = PositionInCircle(i, list.Count, center, radius);
			positionSetter(list[i], pos);
		}
		return list;
	}
	public static List<T> CreateMultipleObjects<T>(int amount) where T : class, new()
	{
		List<T> temp = new List<T>();
		for (int i = 0; i < amount; i++)
		{
			T obj = new T();
			temp.Add(obj);
		}
		return temp;
	}
}

Edited by lwm, 28 August 2012 - 02:55 AM.

current project: Roa


#7 fafase   Members   -  Reputation: 352

Like
0Likes
Like

Posted 28 August 2012 - 03:05 AM

Actually, either I am wrong or this just got me thinking it was it until I figured out it does not do much more than what I was trying to avoid

In the first place I wanted to have a function that could accept different types of object to do the same action.
What I have now is two functions...That is what I wanted to avoid. Then after reading Action is just a function that does not return any value (but is actually slightly slower than a normal function).


There may be a way around this but at the moment this is actually not doing any thing more than what I was trying to avoid.

Edited by fafase, 04 September 2012 - 12:40 AM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS