predefined parameters in function - c#

been looking but not much luck, i want to create a function that only allows certain items to be passed as the first parameter.
e.g. it should only allow the following strings:
"error", "warning", "info"
then the call would be
showme("error");
or showme("warning");
or showme("info");
can this be done? I know I can define
showme(string type){}
but ideally I need showme(string type "error"){}

I suggest an enum
public enum ErrorType {
error,
warning,
info
}
public void ShowMe(ErrorType errorType) {
switch (errorType) {
case ErrorType.error:
//do stuff
break;
case ErrorType.warning:
//do stuff
break;
case ErrorType.info:
//do stuff
break;
default:
throw new ArgumentException("Invalid argument supplied");
break;
}
}
//Invoke the method
ShowMe(ErrorType.info);

As per Rozuur's comment, an Enum would be a clean option. Failing that you could try using code contracts: http://www.cauldwell.net/patrick/blog/CodeContracts.aspx

You can wrap up the logic that depends on your set of values into a class with private constructor, and retrieve instances either through singleton properties or through a factory method.
Something like:
public class StringConstraint
{
private StringConstraint()
public static readonly StringConstraint error = new StringConstraint()
...
public void DoStuffWithStringValue()
{
// Here you do the logic that depends on your particular string value
// e.g. (always) log a message as an error
}
}
This obliges you to only ever pass instances that conform to the logic you want to implement for each of your three strings.

Related

Calling functions with different string names

So I'm trying to make a 2D game (C#) where the player has different skills that they can use. The problem is that I don't know how to call a function with the string containing the skill name. There is always another way to do it, which is by making a really long list full of if-statements to check if the skill is named something, but this seems far from ideal.
Let's say a skill is called "Skill1". Is there any way to call a function called Skill1() by using the string "Skill1"? It would really help with making the code look good.
Thanks in advance
What you're looking for are delegates (and more specifically a dictionary of delegates).
void Main()
{
var things = new Dictionary<string, Action>
{
{"Thing1", DoThing1},
{"Thing2", DoThing2},
{"Thing3", DoThing3},
};
things["Thing1"]();
things["Thing3"]();
things["Thing2"]();
}
public void DoThing1()
{
Console.WriteLine("In Do Thing 1");
}
public void DoThing2()
{
Console.WriteLine("In Do Thing 2");
}
public void DoThing3()
{
Console.WriteLine("In Do Thing 3");
}
For more information, search for Delegates, Actions and Funcs.
Delegates are a good option but if you want to keep it simple you can use switch statement instead of if statements and it will be easy to maintain.
It's basic but maybe it will help
static void Main(string[] args)
{
Console.WriteLine("call skill");
string _skill = Console.ReadLine();
CallSkills(_skill);
}
public static void CallSkills(string skillname)
{
switch (skillname)
{
case "skill1":
//call skill1 method
break;
case "skill2":
//call skill2 method
break;
case "skill3":
//call skill3 method
break;
case "skill4":
//call skill4 method
break;
case "skill5":
//call skill5 method
break;
default:
break;
}
}
An alternative to using a dictionary with delegates is to using a switch expression with delegates.
One possible approach is to create a method that associates all relevant skill names with the appropriate Skill* method, as well as using the discard pattern (_ => ...; here: _ => null) to define a default value for any skillName that does not match any defined skill names in the expression:
private static Action GetSkillAction(string skillName)
{
return skillName switch
{
"Skill1" => Skill1,
"Skill2" => Skill2,
_ => null
};
}
To make it easier to use that method, you could create a method to actually perform a skill (by skill name). This method handles receiving a non-existing skill by only calling the associated action if the action is unlike null:
public static void PerformSkillAction(string skillName)
{
var action = GetSkillAction(skillName);
if (action != null)
{
action();
}
}
Now, calling
PerformSkillAction("Skill1");
will result in a call to Skill1(), whereas calling
PerformSkillAction("Banana");
will not call anything.
Example fiddle here.

Is it possible to return generic class based on enum input?

I am writing a small email templating engine using Razor syntax to fill in the tokens. I have a few email types:
public enum EmailType { Welcome, Reminder }
These types have corresponding templates and models, so for example Welcome email has a template:
<p>Welcome, #Model.Name</p>
and a corresponding model:
public class WelcomeModel { public string Name { get; set; } }
Now I wanted to create a method that will force a correct model for given enum, I would imagine something like this:
public ITemplate<T> GenerateTemplate(EmailType emailType)
{
switch (emailType)
{
case EmailType.Welcome:
return new EmailTemplate<WelcomeModel>();
case EmailType.Reminder:
return new EmailTemplate<ReminderModel>();
// ...
}
where EmailTemplate<T> : ITemplate<T>, so then I could chain the method:
engine
.GenerateTemplate(EmailType.Welcome)
.WithModel(new WelcomeModel()) // this knows it wants WelcomeModel
// and should complain with compiler error otherwise
The code that I've shown here does not compile because T is unknown. However this T cannot be infered:
public ITemplate<T> GenerateTemplate<T>(EmailType emailType)
which leaves me with:
engine
.GenerateTemplate<WelcomeModel>(EmailType.Welcome)
.WithModel(new WelcomeModel());
That works, but I feel like I'm passing redundant information - both enum and model, while you can deduce one from another. I am not sure if I'm missing something from C# or maybe my whole concept is not good. I think I'm in a dead end since I think I cannot return two separate, strongly typed classes from one method.
Is it possible to return generic model based on enum input?
Is it possible to return generic class based on enum input?
No. Not in a way that would be useful to the caller.
Your method returns ITemplate<T>. But T has to be defined as something at compile time. You cannot defer the definition to runtime, except by using late-binding (i.e. dynamic) or non-type-safe mechanisms (which negates the whole point of using generics).
Possibly if you could reframe your question and explain why it is you think it's reasonable to call a method that returns an open generic type ITemplate<T> without the call site understanding what the type parameter T actually is, a helpful solution could be found.
But as stated in your question thus far, the only real answer is, no that can't work and wouldn't make any sense if it could.
Couldn't you just do something like this?
switch (emailType)
{
case EmailType.Welcome:
return engine.GenerateTemplate().WithModel(new WelcomeModel());
case EmailType.Reminder:
return engine.GenerateTemplate().WithModel(new ReminderModel());
}
public ITemplate<T> GenerateTemplate<T>()
{
return new EmailTemplate<T>();
// ...
}
public interface ITemplate<T>
{
void WithModel(T model);
}
public class EmailTemplate<T> : ITemplate<T>
{
void WithModel(T model)
{
// ...
}
}
No, because C# does not support true generic polymorphism and diamond operator yet to allow to write:
public Template<> GenerateTemplate(EmailType emailType)
{
switch (emailType)
{
case EmailType.Welcome:
return new EmailTemplate<WelcomeModel>();
case EmailType.Reminder:
return new EmailTemplate<ReminderModel>();
}
}
The only thing you can do is to simulate that by using a non generic top interface like:
ITemplate<T> : ITemplate
Hence the creator method will returns ITemplate:
public ITemplate GenerateTemplate(EmailType emailType)
{
switch (emailType)
{
case EmailType.Welcome:
return new EmailTemplate<WelcomeModel>();
case EmailType.Reminder:
return new EmailTemplate<ReminderModel>();
}
}
But in your case if you prefer having true generic you need to create several methods:
EmailTemplate<WelcomeModel> GenerateWelcomeTemplate()
=> new EmailTemplate<WelcomeModel>();
EmailTemplate<ReminderModel> GenerateReminderTemplate
=> new EmailTemplate<ReminderModel>();
Then you will check the enum before calling them.
Doing this is more consistant with your code:
if ( EmailType.Welcome )
engine.GenerateWelcomeTemplate().WithModel(new WelcomeModel());
Here the code is more clean.
But I don't understand why you provide WithModel(new WelcomeModel()) after creating EmailTemplate<WelcomeModel>... it's redundant, isn't it?

Convert string to type & pass to generic delegate?

I've been puzzling at this for some time and I'm sure there's an elegant solution... I just can't seem to find it.
I have a web API where the object type being acted on is set by a string parameter. I then need to call a number of generic methods based on that type. Basically what I have is a good old switch statement that I'm in danger of having to repeat several times over, so want to try to encapsulate it within a reusable method:
switch (ModuleName)
{
case "contacts":
return Method1<Contact>();
case "accounts":
return Method1<Account>();
default:
throw new Exception("ModuleName could not be resolved");
}
In other places I'll need to do the same thing but call Method2, Method3, Method4 etc.
I think I should be able to turn this into a method that takes a string and a delegate that accepts the generic type, but I'm stuck on how to construct that. Can anyone point me in the right direction?
Many thanks
Tim
Like Michael Randall says, generics need to be known at compile time. I think you need to reconsider how you encapsulate your business logic here. You could probably solve it like this:
class Example{
void Main(){
var method1 = new LogicMethod1();
TestCase("contacts", method1);
TestCase("Case2", method1);
var method2 = new LogicMethod2();
TestCase("contacts", method2);
TestCase("Case2", method2);
}
void TestCase(string moduleName, LogicBase logic){
switch(moduleName){
case "contacts" : logic.DoTheStuff<Contact>(); break;
case "accounts" : logic.DoTheStuff<Account>(); break;
}
}
}
abstract class LogicBase{
public abstract void DoTheStuff<T>();
}
class LogicMethod1 : LogicBase{
public override void DoTheStuff<T>(){
//Logic for your Method1
}
}
class LogicMethod2 : LogicBase{
public override void DoTheStuff<T>(){
//Logic for your Method2
}
}

Pass type as Type instead of string paramater

I would like to convert this (which is error prone)....
public static void GenerateReport(string report)
{
switch (report)
{
case "ReportA":
// do stuff
break;
case "ReportB":
// do stuff
break;
case "ReportC":
// do stuff
break;
}
}
To this....
public static void GenerateReport<T>()
{
switch (T) // BUT.... how do I handle this?
{
case ReportA:
// do stuff
break;
case ReportB:
// do stuff
break;
case ReportC:
// do stuff
break;
}
}
I have seen a LOT of questions that ask almost the same thing, but none of them have led me to an answer. Like this one, but for me, the solution provided in that thread flat out doesn't work. It throws multiple syntax errors when I try to compile. the solution there says:
switch typeof(T) {
//
}
You don't need generics for that, nor a switch statement with type detecting... instead use method overloading for each of the types and keep the do stuff pieces in their own methods...
public static void GenerateReport(ReportA a) { /*do stuff*/ }
public static void GenerateReport(ReportB b) { /*do stuff*/ }
public static void GenerateReport(ReportC c) { /*do stuff*/ }
Whenever you have if/switch statements where the code will execute differently depending on the input but produce generic output like what you have in your question it is usually a sign that you need to look into doing some refactoring.
In this case the best option would be to use an interface based design and move the logic for executing the various reports into their own types. This will allow you to better manage additional reports on an as needed basis without having to touch the existing code.
public interface IReporter {
void GenerateReport();
}
public class ReporterA : IReporter {
public void GenerateReport() { /* execute report */}
}
public class ReporterB : IReporter {
public void GenerateReport() { /* execute report */}
}
public class ReporterC : IReporter {
public void GenerateReport() { /* execute report */}
}
// The responsibilty of the factory is only to create the correct reporter based on the request
public class ReporterFactory{
public IReporter CreateReporter(string input){
/* the logic here can vary, you can get creative with Attributes
and name each report type and use reflection to create the
correct report type. You can also use an Enum and use that as an attribute value over
each Reporter type. There are many ways to handle it.
*/
}
}
/* your refactored method */
public static void GenerateReport(string report)
{
/* again, creation pattern could be based on something other than a string. It depends on how you want to differentiate your reporters*/
var reporter = new ReporterFactory().CreateReporter(report);
reporter.GenerateReport();
}
The key point about generics is that if the thing you are doing isn't roughly the same for each final T, then it isn't actually generic and you shouldn't be doing it that way.
Good candidates here might include:
an enum
polymorphism (a virtual / abstract method)
passing in a Type instance
but... not generics. The reason the language isn't helping you is because this isn't a good fit. That said: you could do:
if(typeof(T) == typeof(Foo)) {
// foo
} else if (typeof(T) == typeof(Bar)) {
// bar
} ...
but; that is kinda missing the point of generics.
You can do it like this:
public static void RunIfEqual<TLeft, TRight>(Action action)
{
if (typeof(TLeft) == typeof(TRight))
{
action();
}
}
...
RunIfEqual<T, ReportA>(()=> ...);
RunIfEqual<T, ReportB>(()=> ...);
RunIfEqual<T, ReportC>(()=> ...);
Or even better way, you can define some ReportGeneratorFactory, that will choose which generator to use for this type and return it to you. Then you can just call GenerateReport on it.

How do I write a C# method to return a Func<T> based in an enum parameter?

I have a set of methods each of which return an ObservableCollection for various types of T, and would like to be able to write a factory method that returns these methods, based on an enum value sent in. For example, suppose I have the following highly realistic methods...
public ObservableCollection<Gribble> GetGribbles() {
return new ObservableCollection<Gribble>();
}
public ObservableCollection<Gribulator> GenerateGribulators() {
return new ObservableCollection<Gribulator>();
}
public ObservableCollection<Knepple> MakeKnepples() {
return new ObservableCollection<Knepple>();
}
...and the following enum...
public enum ListNames {
Gribbles,
Gribulators,
Knepple
}
Then I would like to be able to do this...
Func<ObservableCollection<Gribble>> someGribbles =
MakeFunc<Gribble>(ListNames.Gribbles);
The reason for this is that I have a helper class with a signature like this...
public void GetList<T>(ListNames listName,
Func<ObservableCollection<T>> serviceCall,
Action<ObservableCollection<T>> handleList)
serviceCall is the method that gets the list, and handleList is a callback method. At the moment, wherever this method is called, the code has to pass the actual function that gets the list.
However, this is proving to be a bad design choice, as it means that if two parts of the code both make a call to GetList for a particular list, they could pass in two different service calls, which will cause inconsistent results. I want to encapsulate the service call in the MakeFunc method, which would be called from GetList, meaning that the code that uses GetList never sees the actual service call, and so can't do anything wrong.
I have tried a few things, but am struggling to get anything that will compile. The closest I have got is the following...
public Func<ObservableCollection<T>> MakeFunc<T>(ListNames listName) {
switch (listName) {
case ListNames.Gribbles:
return GetGribbles;
case ListNames.Gribulators:
return GenerateGribulators;
case ListNames.Knepple:
return MakeKnepples;
default:
throw new ArgumentException("Unknown list name");
}
}
...but this gives a compiler errors along the lines of "GetGribbles() has the wrong return type" and the tooltip that pops up when I hover my mouse over GetGribbles in the MakeFunc method says
Expected a method with 'ObservableCollection<T> GetGribbles()' signature
Is it possible to do what I want? If so, anyone able to explain what I did wrong?
I'm using C# 4.0 in Visual Studio 2010 if it makes any difference.
Well if the Gribble, Gribulator, and Knepple classes share a common base type or implement a common interface, you can just do this:
public Func<ObservableCollection<ICommonInterface>> MakeFunc(ListNames listName)
{
...
}
If they don't have a common base type or interface, you'd have to do this:
public Func<ICollection> MakeFunc(ListNames listName)
{
...
}
Which, admittedly, is not a very good solution. Note: you can replace ICollection with INotifyCollectionChanged or whatever non-generic interface that you need most.
In both cases, you have to rely on the caller to specify the data type (even if the caller specifies the enum value as well). So, you could also get rid of the enum, and go for something like this:
public Func<ObservableCollection<T>> MakeFunc<T>()
{
if (typeof(T) == typeof(Gribble))
return () => GetGribbles() as ObservableCollection<T>;
if (typeof(T) == typeof(Gribulator))
return () => GenerateGribulators() as ObservableCollection<T>;
if (typeof(T) == typeof(Knepple))
return () => MakeKnepples() as ObservableCollection<T>;
throw new ArgumentException("Unknown list name");
}
Then the caller could simply write:
var gribblesFunc = MakeFunc<Gribble>();

Categories

Resources