C# function overloading question

Started by
10 comments, last by benryves 17 years, 1 month ago
Im trying to find out how to approach a function overloading issue i have. Ill start out with a few details of what my goal is. Heres a small code segment of my item class,TextItem, including the constructor.

private int	damage,stamina,strength,agility,intellect,defense,proc,hand;
	
	public TextItem(string oname,int odamage,int ostamina,int ostrength,
									int oagility,int ointellect,int odefense,int oproc,int ohand)
	{
		this.name=oname;
		this.damage=odamage;
		this.stamina=ostamina;
		this.strength=ostrength;
		this.agility=oagility;
		this.intellect=ointellect;
		this.defense=odefense;
		this.proc=oproc;
		this.hand=ohand;
	}

This allows creation of an item, but i have to enter all attributes of the item for it to work. If the item should only have damage and stamina, i only want to enter those 2 attributes. The following creates a new item (sword) and puts it in the 4th slot in the player's inventory: me.SetInventoryItem(4,new TextItem("Sword",3,2,5,0,0,0,TextItem.R_HAND,1));//give yourself a Sword (testing) Ive done something similar at school programming in &#106avascript, where i only had to enter what attributes i wanted. It was 1 constructor (or whatever JS uses) but i guess it "nulls" the unentered parameters. The following is something like what i used at school in JS: a = Item(NAME,"Sword",DAMAGE,3,STAMINA,5) Since &#106avascript &#111;nly supports 16 arguments (i think), i could &#111;nly use 8 attributes (before an attribute must be the attribute type IE: Stamina) but thats beyond the point. Can i do something similar in C#, instead of having a bunch of overloaded functions? Here is an example of what i want to do, using 1 function: <b>me.SetInventoryItem(4,new TextItem(TextItem.NAME,"Sword",TextItem.STAMINA,3));//give yourself a Sword (testing)</b> The constructor would read something like: <b> public TextItem(ATT1,VAL1,ATT2,VAL2,ATT3,VAL3,ATT4,VAL4)</b> This is what i dont want: <b> public TextItem(ATT1,VAL1){} public TextItem(ATT1,VAL1,ATT2,VAL2){} public TextItem(ATT1,VAL1,ATT2,VAL2,ATT3,VAL3){} public TextItem(ATT1,VAL1,ATT2,VAL2,ATT3,VAL3,ATT4,VAL4){}
Advertisement
Not in the current iteration (iirc). The closest you can get is setter chaining:
class foo{    public foo SetOne(string something){...; return(this);}    public foo SetTwo(string something){...; return(this);}}SetInventoryItem(4, (new TextItem).SetOne("Sword").SetTwo("KickAss"));


Though you should probably should prefer neither. Having empty constructors is generally the most consistent, reliable, and adaptable design for things. More importantly, such one line multi-assignment constructs are often less clear and/or readable than their many-line single assignment alternatives:
class TextItem{    public string Name{       get{...}       set{...}    }    public string Damage{       get{...}       set{...}   }}TextItem KickAssSword = new TextItem();KickAssSword.Name = "Sword";KickAssSword.Damage = "4000000";SetInventoryItem(4, KickAssSword);


Most programmer time is spent debugging and maintaining, not creating. Spending the little extra time during creation to ensure the code is clearly written will save you time later.

You could use a variable argument list. you can do that by using the "params" keyword with an array, as such:

public TextItem(string oname,params int[] attributes)	{		//you would extract the attributes from the array here, you would want to check the number of attributes available first though. Also you should explicitly state in the documentation(if any) what the ordering of the parameters are.	}


you would then use it as such:
TextItem("something",1);TextItem("Something else", 1, 5, 29);......


Hope this helps.
Yes, it is possible to use variadic funtions with the "params" keyword as deathtrap noted, but that's probably not the most elegant solution to your problem. For one, if you need a function that takes parameters of different types, you have to do a lot of type checking yourself to make sure everything works. For your specific problem, IMHO this would be a kludgy solution at best.

Personally, I would go with the method Telastyn recommended. It's simpler, cleaner, easier to maintain, and much more "C#-like". [smile]
Thanks for the replies. I looked each method over and by the looks of it, the setter chaining looks the best for what im doing.

class foo{    public foo SetOne(string something){...; return(this);}    public foo SetTwo(string something){...; return(this);}}SetInventoryItem(4, (new TextItem).SetOne("Sword").SetTwo("KickAss"));


Ive never seen anything like this, so im kind of confused on where the class foo goes, and what foo is (ive seen "foo" a lot but im assuming its an <insert class name here> type thing), and what ... is. I have seen ... in Lua (scripting language), but i couldnt find out what it stands for, even after searching google and the lua manual.

I definetly like how creating items is done this way. I also like the
public TextItem(string oname,params int[] attributes)
This was the more accurate method i was looking for, however setter chaining looks easier for me to use as far as editing items goes. Plus i wont have to deal with all the array extracting and the bugs that would come with, and if i decide to add more attributes to items (such as increasing chance to dodge by 0.25), i can do it quick using setter chaining.

Yes, in the example foo is a generic label placeholder. '...' represents "actual code, which I am too lazy to reproduce and is not terribly essential to communicating the general concept".

... is used in certain languages akin to the params keyword in C#. I still don't think it's a good idea, but at least it's an informed idea.
I changed how the TextItem class works and well.. it doesnt work.

I think i misinterpreted SetInventoryItem(4, (new TextItem).SetOne("Sword").SetTwo("KickAss"));

It doesnt happen to mean:
Create a new TextItem, execute method "SetOne(string)", execute method "SetTwo(string)" does it?


Heres some new code (TextItem.cs)
//declare variables is still up herepublic TextItem()//constructor{	//set attributes to 0 and let methods change them	this.name="";	this.damage=0;	this.stamina=0;	this.strength=0;	this.agility=0;	this.intellect=0;	this.defense=0;	this.proc=0;	this.hand=0;}	//set name method	public void SetName(string n)	{		this.name=n;	}	//set damage method	public void SetDamage(int d)	{		this.damage=d;	}


And heres the main class creating the sword:
me.SetInventoryItem(4,(new TextItem).SetName("Sword").SetDamage(3));

I get error:
Quote:error CS1526: A new expression requires () or [] after type

PS: The error takes place on the line quoted above.

me.SetInventoryItem(4,(new TextItem()).SetName("Sword").SetDamage(3));
I tried that too but i get error:
Quote:
error CS0023: Operator '.' cannot be applied to operand of type 'void'


And i dont see how making it return a value would help, else im better off using public TextItem(string oname,params int[] attributes)
Quote:
Create a new TextItem, execute method "SetOne(string)", execute method "SetTwo(string)" does it?


What else would it mean?

Quote:
And i dont see how making it return a value would help...


It kinda has to doesn't it? Otherwise what instance does SetName and SetDamage operate upon?

(new TextItem()).SetName("Sword").SetDamage(3);


Is:
Create new TextItem with default values
and Set Name to "Sword" on what it returns
and Set Damage to 3 on what that returns.


See yet why doing properties is much clearer than setter chaining? [grin]

This topic is closed to new replies.

Advertisement