Sign in to follow this  
javasirc

C# function overloading question

Recommended Posts

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 javascript, 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 javascript only supports 16 arguments (i think), i could only 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: me.SetInventoryItem(4,new TextItem(TextItem.NAME,"Sword",TextItem.STAMINA,3));//give yourself a Sword (testing) The constructor would read something like: public TextItem(ATT1,VAL1,ATT2,VAL2,ATT3,VAL3,ATT4,VAL4) This is what i dont want: 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){}

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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.

[quote]

class foo{
public foo SetOne(string something){...; return(this);}
public foo SetTwo(string something){...; return(this);}
}

SetInventoryItem(4, (new TextItem).SetOne("Sword").SetTwo("KickAss"));

[/quote]

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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 here
public 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.

Share this post


Link to post
Share on other sites
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)

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
javasirc: you changed the return type and left of the return (this);, it needs to return itself since the next SetN("...") is called on the value returned by the previous SetN("...")

I would advise you to use properties instead though like Telastyn suggested.

Share this post


Link to post
Share on other sites
Another option is to rather than do this:

class Demo {
int a, b, c;

public Demo(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}

public Demo(int a, int b) {
this.a = a;
this.b = b;
this.c = 3;
}

public Demo(int a) {
this.a = a;
this.b = 2;
this.c = 3;
}

public Demo() {
this.a = 1;
this.b = 2;
this.c = 3;
}

}



...you could do this:

class Demo {
int a, b, c;

public Demo(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}

public Demo(int a, int b) : this(a, b, 3) { }

public Demo(int a) : this(a, 2) { }

public Demo() : this(1) { }

}



You still need to write multiple constructors, but they get easier and easier to write. [smile]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this