Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I am writting some code in C# and I noticed scenario like below. I wonder how can I make this more elegant and easy to maintain.
If I have following scenario with overloads
public void DoSmtg(string a) { DoSmtg(a, 0, 0f); }
public void DoSmtg(string a, int x) { DoSmtg(a, x, 0f); }
public void DoSmtg(string a, int x, double d) { // method logic }
say now I need to add another bool parameter. I would have to modify this to
public void DoSmtg(string a) { DoSmtg(a, 0, 0f, false); }
public void DoSmtg(string a, int x) { DoSmtg(a, x, 0f, false); }
public void DoSmtg(string a, int x, double d, bool doIt) { // method logic }
This is a very simple example. It is possible to have say 10 more versions of DoSmtg() method. Clearly, this code smells. While overloading is quite valid, it obviously makes it hard to maintain this code since:
there are many methods to be written
it is not obvious which method is called until careful investigation (especially if method has more parameters)
method gets poluted by growing parameter list
the new parameter added requires changes at many places (think about the methods above called from many different locations)
What would be an elegant, simple and good way to avoid something like this?
You could try adding all the parameters on one function, using default values and name the parameters when you call the function:
public void DoSmtg(string a, int x=0, double d=0f, bool doIt=false) {
// method logic
}
When calling the function, you would then do:
DoSmtg("yo!")
DoSmtg("yo!", d:0.59, doIt:true)
You could wrap all the parameters up in a POCO:
public class SomethingParameters
{
public string A { get; set; }
public int X { get; set; }
public double D { get; set; }
public bool DoIt { get; set; }
}
Then the method signature becomes:
public void DoSmtg(SomethingParameters parameters) { // method logic }
I like this pattern because it's easy to extend in the future. If you need to add five more parameters, or optional parameters, no problem!
You can call it like:
var parameters = new SomethingParameters()
{
A = "foobar",
X = 123,
D = 0.123,
DoIt = false
}
DoSmtg(parameters);
If you have a lot of code calling the old method signature that you don't want to break, you could keep your existing overloads but have them call the new one:
public void DoSmtg(string a, int x, double d, bool doIt)
=> DoSmtg(new SomethingParameters()
{
A = a,
X = x,
D = d,
DoIt = doIt
});
I prefer the option of using a separate class for parameters. But perhaps, as you said, you're already calling the method in multiple places and don't want to modify it.
In that case you can add an optional parameter:
public void DoSmtg(string a, int x, double d, bool doIt = false)
Nothing has to change anywhere else except that you can supply the parameter if you choose to.
If you find yourself doing this I'd still write the extra overload using a class anyway and start using that. Optional parameters can start to get messy too if there are too many of them.
Related
I would like to design something that gets the distance between two things. However, these things can be manifest in many obnoxious forms.
Let's say we have a set of classes. (Not necessarily base and derived)
Cat, CoolCat, ReallyCoolCat
All of them have a way to access a position. I would like to write a function call 'DistanceBetween' that gets the distances between the cats.
I can make overloads:
public static float DistanceBetween(Cat cat1, Cat cat2)
{
return Mathf.Abs(cat1.position - cat2.position);
}
public static float DistanceBetween(CoolCat cat1, CoolCat cat2)
{
return Mathf.Abs(cat1.transform.position, cat2.transform.position);
}
// ... etc...
However, then I would have cases where I need to know the distance between a Cat and a CoolCat or the distance between a CoolCat and a ReallyCoolCat. That means...
public static float DistanceBetween(Cat cat1, CoolCat cat2)
{
return Mathf.Abs(cat1.position, cat2.transform.position);
}
public static float DistanceBetween(CoolCat cat1, ReallyCoolCat cat2)
{
return Math.Abs(cat1.tranform.position, cat2.kittyVariables.position);
}
// ... etc ...
But then it just seems arbitrary cause I can rearrange the order of my arguments and my function wouldn't work. So I have to make...
public static float DistanceBetween(CoolCat cat1, Cat cat2)
{
return Mathf.Abs(cat1.tranform.position, cat1.position);
}
public static float DistanceBetween(ReallyCoolCat cat1, CoolCat cat2)
{
return Math.Abs(cat1.kittyVariables.position, cat2.transform.position);
}
// ... etc ...
So This means the amount of code per cute kitties I make grows by n^2. This amount of code growth is not acceptable due to how many cute kitties I want to make. I cannot implement inheritance because my cute kitties (though similar in name) have very different features and are unique. (I could add doggies and the such too.) So what I am thinking is to create an interface 'IDistanceable' that says the implementing class has a 'Position' property and implementing it in each kitty. But this starts to seem like overkill though, all I wanted was something that can rearrange my arguments and make Func(a,b) equal to Func(b,a)...
I don't really know what to do... both solutions (write 500 functions or make interface and lots of junk) both seem wrong.
The interface will NOT work due to the inability to modify some of the cute kitty classes...
Please help me and my cute kitties! Thanks!
If you can't modify the classes, you're best off wrapping them in something you can modify. That way, you can centralize the class-specific logic in one place (the different constructors).
class CatWrapper
{
private int position { get; set; }
public CatWrapper(Cat cat) { ... }
public CatWrapper(CoolCat cat) { ... }
public CatWrapper(ReallyCoolCat cat) { ... }
public DistanceFrom(CatWrapper other) { ... }
}
This is a purely academic answer, since #Andrews Pilser's is far superior for almost any real-world project, but this will solve it for any class that has any conceivable way of representing a location. It makes heavy use of lambda-expressions, and generics, and requires no control over the underlying classes.
The code was written in LINQPad, so it may look a little odd, but it is standard C# (version 7) that can be snapped right in to Visual Studio. File available here.
This uses a Dictionary to store a ToPointConverter for any Type that can be converted to a Point. A ToPointConverter is created from a static method Create that accepts a lambda that returns a Point from the specific generic T.
As you can see, I provide 3 example "kitty" classes that each store their location in completely different ways. The main function creates a converter for each, storing it in the dictionary of converters, and then calculates the distance between the different combination of "kitties". (I may have gotten my distance function wrong, it's late, but that is a minor detail.)
It produces this output:
2.23606797749979
9.05538513813742
2.23606797749979
8.06225774829855
9.05538513813742
8.06225774829855
void Main()
{
//Define conversion functions for anything that can be converted.
converters.Add(typeof(KittyA), ToPointConverter<KittyA>.Create(kitty => kitty.Location));
converters.Add(typeof(KittyB), ToPointConverter<KittyB>.Create(kitty => new Point { X = kitty.X, Y = kitty.Y }));
converters.Add(typeof(KittyC), ToPointConverter<KittyC>.Create(kitty => kitty.MyLocation));
//Declare some kitties
var kitty1 = new KittyA { Location = new Point { X = 1, Y = 1 } };
var kitty2 = new KittyB { X = 3, Y = 2 };
var kitty3 = new KittyC { MyLocation = new Point { X = 2, Y = 10 } };
//Calculate the distances
GetDistance(kitty1, kitty2).Dump();
GetDistance(kitty1, kitty3).Dump();
GetDistance(kitty2, kitty1).Dump();
GetDistance(kitty2, kitty3).Dump();
GetDistance(kitty3, kitty1).Dump();
GetDistance(kitty3, kitty2).Dump();
}
private Dictionary<Type, IToPointConverter> converters = new Dictionary<Type, IToPointConverter>();
//A helper function that does the converts the passed objects in to Points, and calculates the distance between them.
private double GetDistance(object obj1, object obj2)
{
var point1 = GetConvrterFor(obj1).Convert(obj1);
var point2 = GetConvrterFor(obj2).Convert(obj2);
return Math.Sqrt(Math.Pow(point2.X - point1.X, 2) + Math.Pow(point2.Y - point1.Y, 2));
}
//Another helper that gets the IToPointConverter for the object instance passed in.
private IToPointConverter GetConvrterFor(object obj) => converters[obj.GetType()];
//This generic class stores a lambda expression that converters from T to a Point
public class ToPointConverter<T> : IToPointConverter
{
public static ToPointConverter<T> Create(Func<T, Point> conversion)
{
return new ToPointConverter<T>(conversion);
}
private ToPointConverter(Func<T, Point> conversion)
{
_conversion = conversion;
}
private Func<T, Point> _conversion;
public Point Convert(T obj) => _conversion(obj);
Point IToPointConverter.Convert(object obj) => Convert((T)obj);
}
//The non-generic interface for the converter (so different closed generic types can be stored in the same dictionary, and have their Convert method called.)
public interface IToPointConverter
{
Point Convert(object obj);
}
//Just a standard structure to hold a location. You would use whatever native location class your framework has.
public struct Point
{
public int X;
public int Y;
}
//Some example kitty classes
public class KittyA
{
public Point Location { get; set; }
}
public class KittyB
{
public int X { get; set; }
public int Y { get; set; }
}
public class KittyC
{
public Point MyLocation { get; set; }
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Sometimes it happens that I want to use a lot of Method As variables in Method B.
Usually its quite a pain to pass all the variables to this method, especially if I have to do this a lot of times (but cannot simply copy paste, because some things change) or am just to lazy.
Is there such a thing like a "inner Method"? Or some concept to handle this in an easy way?
What I want to do:
public void A()
{
int a = 4;
string b = "Hello World";
B(ref vals);
//Or like so
C(ref current);
}
public void B(ref AllValues)
{
a = 3;
...
}
public void C(ref MethodThatSharesAllValues method)
{
method.a = 3;
...
}
If they all are in the same class
You can configure them as class variables:
public class MyClass{
//set this as private/protected/public or nothing and you can also set a default value
int a;
public void A()
{
a = 4;
string b = "Hello World";
B();
C();
}
public void B()
{
a = 3;
...
}
public void C()
{
a = 3;
...
}
}
Elseway
public static class MyClassA{
public static int a = 0;
public static void MethodA(){
this.a = 3;
}
}
now from method B you can access MyClassA
int myExValueA = MyClassA.a;
Elseway you gotta pass them as parameters
hope this helps
You can create a class which will hold your parameters and then pass only an instance of this class
public void metA(Parameters input)
{
input.a = 5;
input.c = "hello";
metB(input);
}
public void metB(Parameters input)
{
input.b = 10;
}
public class Parameters
{
public int a;
public int b;
public string c;
}
You can declare the variables static in a class header and use them as you like, private if are in the same class, protected for child classes, internal or public else. Or box the variables in a class like this:
public class Foo
{
public int A { get; set; }
public int B { get; set; }
public string C { get; set; }
}
If passed variables are the same type you can use data structure like int[] or string[] or List<int> or List<string> and pass them without ref but this has the disadvantage that more than often you would not use all varibales from the structure as it is also the case with the class boxing variant.
Something like the following:
public void foo() {
int a = 10;
// ...
}
public void foo_bar() {
// "a" is not in scope for foo_bar, so this won't compile
a = 20;
// ...
}
would definitely be invalid. I don't think that this was what you were driving at in your question though.
You can do something somewhat similar to what you ask for using closures but they're a bit tricky to work with. Basically, something like this would be valid (and I'm not sitting in front of an IDE so forgive me if the syntax is a little off):
Func<int> GetCounter() {
int count = 0;
// This will capture the count variable from its context
Func<int> method = () => ++count;
return method;
}
While a fair number of languages (including some versions of C++ now I guess) have closures (or some similar variant), there seems to be little consistency in exactly how they work across languages (e.g. on whether the "count" variable should be immutable once it's captured) so it's important to check the documentation for the language you're using (in this case, C#) to understand exactly how they work.
In terms of the first code sample I provide, I doubt that that's what you were asking about, but just as a brief digression you probably wouldn't really want it to be the allowable anyway (and again I suspect that this isn't the syntax/semantics you're asking about) as it would quickly lead to unexpected/undefined behavior. For example:
If you have a local variable a that's initialized in Foo() and you refer to it in Foo_Bar() before you run Foo(), what should its value be?
If you run Foo() to initialize the variable, edit the variable in Foo_Bar(), and then run Foo() again, should you re-initialize the variable or allow it to remain what Foo_Bar() set it to?
Is it safe to garbage collect a local variable after the method call completes, or might it be referred to again?
See the following:
public class SomeObject
{
public int SomeProperty { get; set; } = 6;
// ...
}
public class SomeOtherObject
{
// ..
}
void foo() {
// What is the content of "a" before foo() runs?
object a = new SomeObject();
// Which "a" should this refer to - the one in foo() or the one in foo_bar()?
// Also, is this a valid cast given that we haven't specified that SomeOtherObject can be cast to SomeObject?
var b = (SomeObject)a;
// If we run foo() again, should "b" retain the value of SetProperty or set it back to the initial value (6)?
b.SetProperty = 10;
// ...
// Is it safe to garbage collect "a" at this point (or will foo_bar refer to it)?
}
void foo_bar() {
object a = new SomeOtherObject();
// ...
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I'm working on an Card Game development in C#, and I don't know how to do the following:
I have my Card class, which has a List of actions that are attacks in which that card can perform.
These attacks are a custom class named Act (in which I called Rules in the example).
When I load my cards I call an Inicialize method that I created that inicialize the List of cards, as well as the List of Attacks of each card.
I Want to be able to express my Attacks as an multiple Method call with parameters that will be called only when I call that Attack for execute.
For example, something like that
ActionList = new List<CardRule>();
ActionList.Add(new CardRule()
{
Description = "Cause 20 damage, then causes burn status.",
Rules = Damage(20).CauseStatus(Status.Burn);
});
I want to define the action(which I called Rules) as an multiple method call, passing parameters,
And call that Rules.Execute() to perform all method call, etc..
I Know that its something related to delegates, but I don't know how to do this calling multiple methods with predefined parameters.
Thank you in advance and sorry for bad english, I'm new at Stack Overflow also..
Regards,
What you're looking for isn't actually a delegate, but a class which tracks what needs to be done. This is a pattern used often by fluent APIs, but it's relatively simple to create something for your example.
For your example, you may have an IActionConfiguration interface, for example:
public interface IActionConfiguration
{
void PerformAction(MyTarget target);
}
Now, you'll want a few different implementations. For example, one which represents damage:
class DamageActionConfiguration : IActionConfiguration
{
private int m_damageStrength;
public DamageActionConfiguration(int strength)
{
m_damageStrength = strength;
}
public void PerformAction(MyTarget target)
{
target.Health -= strength;
}
}
And another one to represent a status effect:
class CauseStatusActionConfiguration : IActionConfiguration
{
private Status m_status;
public CauseStatusActionConfiguration(Status status)
{
m_status = status;
}
public void PerformAction(MyTarget target)
{
target.StatusEffects.Add(m_status);
}
}
Now, you'll also one an implementation which represents multiple actions.
class CompositeActionConfiguration : IActionConfiguration
{
private IActionConfiguration m_firstWrappedConfiguration;
private IActionConfiguration m_secondWrappedConfiguration;
public CompositeActionConfiguration(IActionConfiguration first, IActionConfiguration second)
{
m_firstWrappedConfiguration = first;
m_secondWrappedConfiguration = second;
}
public void PerformAction(MyTarget target)
{
m_firstWrappedConfiguration.PerformAction();
m_secondWrappedConfiguration.PerformAction();
}
}
This is incredibly simplified, but good enough for our example. Now you have a class (CompositeActionConfiguration) which can represent multiple actions - all you need is the magic that lets you chain them together easily.
public static class ActionRules
{
//First, you want a few static methods which can start a chain:
public static IActionConfiguration Damage(int strength)
{
return new DamageActionConfiguration(strength);
}
public static IActionConfiguration Status(Status status)
{
return new CauseStatusActionConfiguration(status);
}
// Next, some extension methods which allow you to chain things together
// This is really the glue that makes this whole solution easy to use
public static IActionConfiguration WithDamage(this IActionConfiguration source, int strength)
{
return new CompositeActionConfiguration(source, Damage(strength));
}
public static IActionConfiguration WithStatus(this IActionConfiguration source, Status status)
{
return new CompositeActionConfiguration(source, Status(status));
}
}
That's it. This gives you a solution which does more or less what you want. You would define your Rules property as an IActionConfiguration, then you can consume it like this:
var card = new CardRule()
{
Description = "Cause 20 damage, then causes burn status.",
Rules = ActionRules.Damage(20).WithStatus(Status.Burn);
};
card.PerformAction(target);
Is it possible to do a stack like this
Stack<Location> labels = new Stack<Location>()
labels.Push(label1, 400, 100)
labels.Push(label2, 400, 200)
I need to know if this is possible. If it is please tell. Thanks
Yes, although I wouldn't advice it. Create an extension method and place it into a public static class. The following example assumes that there's a constructor accepting a string and two integers for the class Location.
public static class ExtensionMethods
{
public static void Push(this Stack<Location> stack, string label, int x, int y)
{
stack.Push(new Location(label, x, y));
}
}
For that matter,
You can also also create a LocationStack class which wraps your Stack<Location>, and exposes the friendly method that you are looking for!!
I have a static function in a class with two overloads. Both the overloads are quite the same with the exception of one or two parameters. string body is the only necessary parameter in my function which you can see, rest are optional parameters. But parameters object y and int x shouldn't come together. So i had to write two overloads as below. I provide a sample code:
public static void Foo(string body, string caption = "", int x = 0)
{
//leave it to me
}
public static void Foo(string body, string caption = "", object y = null)
{
//leave it to me
}
Now when I want to call this static function from other classes, since string body is the only required parameter, I try to write at times:
ClassABC.Foo("hi there");
Which gives me this: The call is ambiguous between the following methods or properties. I know why this happens, and what ideally the solution is. But I need to know if anything else could be done in C# to tackle this.
Obviously, the compiler is confused as to choose which function to go for, but I wouldnt mind the compiler going for any considering both are the same without int x and object y. Three questions basically:
Is there anyway to tell the compiler "take any" (almost impossible task, but still let me know)?
If not, is there anyway I can create a single function to handle both cases? Something like this:
public static void Foo(string body, string caption = "", int x = 0 || object y = null) // the user should be able to pass only either of them!
{
//again, I can handle this no matter what
}
Any other workarounds to solve this?
EDIT:
I can not rename the two functions.
I can not create more overloads. It's not just these combinations possible. I should be able to write Foo(string body, int x) etc. So goes. Its virtually impossible to handle all conditions if parameters are more than say, 10!. In short, optional parameters are a must.
Add a separate overload to handle the cases with one or two arguments.
public static void Foo(string body, string caption = "")
{
}
public static void Foo(string body, string caption, int x)
{
}
public static void Foo(string body, string caption, object y)
{
}
If you need to handle arbitrary combinations of arguments, then perhaps it's time to group your optional arguments into a class of their own:
public sealed class Options
{
public string Caption { get; set; }
public int X { get; set; }
public object Y { get; set; }
}
public static void Foo(string body, Options options)
{
}
If you're not sure do it the safe way.
public static void Foo(string body)
{
}
public static void Foo(string body, string caption)
{
}
public static void Foo(string body, string caption, int x)
{
}
public static void Foo(string body, string caption, object y)
{
}
EDIT: Since you mentioned that there may be 10 or so parameters you need a more general solution.
There is an option with variable arguments. Check the type of each argument and act accordingly:
public static void Foo(string body, param object[] the_rest_of_arguments)
{
}
If two arguments have the same type but different functionality (string caption and, say, string author) then you need something else. You can have a class that has all the arguments as members. User should fill the object of that class and pass that object as only argument:
public class FooArguments
{
public string caption;
public int x;
public object y;
}
public static void Foo(string body, FooArguments the_rest_of_arguments)
{
}
Instead of new class FooArguments you can have Dictionary<string,object> where key is the name of the argument, and value is the the argument itself.
If the function is called with inappropriate combination of arguments then just throw an exception.
provide a wrapper
public static void Foo(string body)
{
public static void Foo(string body, "", null);
//leave it to me
}
or something similiar
How about implementing the second variant only and checking the actual type of the 'object' passed as third parameter (if any at all) using GetType()? This however assumes skipping the third parameter (x = 0 or y = null) would lead to the same results. Note that this approach offers less options for optimization as the selection has to happen at runtime - not compile time (unless the compiler is able to differentiate that).