I have a method that I would like to pass an option to, but as a switch. It is hard for me to explain so I will include the class:
class Special
{
int Var1;
int Var2;
public void Add1(int option, int variable)
{
int ToReturn;
ToReturn = variable + 1;
switch(option)
{
case 1:
Var1 = ToReturn;
break;
case 2:
Var2 = ToReturn;
break;
}
}
}
Is there a way I can limit the value of option to 1 or 2? Can I add any information to the Add1 so that when it is called it informs the programmer as to which values it may be, and what each option does?
I have given an example class, but my class contains many more variables this may apply to.
Yes:
public enum Option
{
Option1,
Option2
}
public void Add1(Option option, int variable)
{
int ToReturn;
ToReturn = variable + 1;
switch(option)
{
case Option1:
Var1 = ToReturn;
break;
case Option2:
Var2 = ToReturn;
break;
}
}
Looks like you want to use enumerations, basically placeholders for statically defined values.
I could think of a number of ways to do what you are asking however if I was in your scenario (providing I have understood your question correctly) I would be using an enum...
enum Options {
Option1 = 1,
Option2 = 2
}
class Special
{
int Var1;
int Var2;
public void Add1(Options option, int variable)
{
int ToReturn;
ToReturn = variable + 1;
switch(option)
{
case Options.Option1:
Var1 = ToReturn;
break;
case Options.Option2:
Var2 = ToReturn;
break;
}
}
}
Related
When using a custom class there is a switch that takes in an int. The switch then fills out the class where some cases have a num, and some do not. The int can range virtually anywhere in the application, but some cases do not have one. When the newClass is viewed the user needs to see what ones do not have a number. This code below works fine, except that there is an warning that needs to be removed for :
"The result of comparing value type newClass.num with null is true"
and
"Unreachable code detected" for the false part of the statement.
Is there a method or best practice that can be used to test for nullReferenced parts of a class?
What is this type of situation called(ie, non-nullable refencing, nullReference testing) (...because I don't know what to search for)?
using system.generic;
using system.generic.collections;
public Class newClass{
string name;
int num;
public newClass(int index){
switch(index){
case 1:
num = 20;
name = "returns true";
break;
case 2:
// no num here
name = "returns false";
default :
break;
}
}
}
public otherClass{
newClass foo = new newClass(1);
newClass bar = new newClass(2);
List<newClass> newClassList = new List<newClass>();
newClassList.add(foo);
newClassList.add(bar);
foreach(newClass nc in newClassList){
if(nc.num != null){
print("True");
} else {
print("False");
}
}
}
the value is defined as an int which is a value type in C#, thus not nullable. You can remove your warnings by either making it an int?, i.e. a nullable integer. Or, in case 0 is not a possible value for num in your scenario, change your condition to be:
// default(int) will be 0, the default value for a C# int
if(nc.num != default(int)){
print("True");
} else {
print("False");
}
You can't check variable with null except it's be nullable (like string)
so: 1) modify : int num;
to be:
int? num;
2) remove else
foreach (newClass nc in newClassList)
{
if (nc.num != null) //warning will disappear because num is nullable
{
print("True");
}
print("False");
}
I modified your code to avoid compilation error
using System.Collections.Generic;
public class newClass
{
public string name;
public int? num;
public newClass(int index)
{
switch (index)
{
case 1:
num = 20;
name = "returns true";
break;
case 2:
// no num here
name = "returns false";
break;
default:
break;
}
}
}
public class otherClass
{
newClass foo = new newClass(1);
newClass bar = new newClass(2);
List<newClass> newClassList = new List<newClass>();
public otherClass()
{
newClassList.Add(foo);
newClassList.Add(bar);
foreach (newClass nc in newClassList)
{
if (nc.num != null)
{
print("True");
}
print("False");
}
}
private void print(string msg)
{
throw new System.NotImplementedException();
}
}
I have implemented the enum below:
public enum CaseOriginCode
{
Web = 0,
Email = 1,
Telefoon = 2
}
I would like to get the enum int value by a string. Something like this:
public void setCaseOriginCode(string caseOriginCodeParam)
{
int caseOriginCode = CaseOriginCode.GetEnumByString(caseOriginCodeParam);
// do something with this integer
}
So my input is a string and my output needs to be an int.
Or is it better to implement an dictionary with an key value. The key will be the string and the will be an int.
Please try with the below code snippet.
public void setCaseOriginCode(string CaseOriginCode)
{
int caseOriginCode = (int)(CaseOriginCode)Enum.Parse(typeof(CaseOriginCode), CaseOriginCode);
}
Let me know if any concern.
One thing to note, if after casting you are getting a result of 0, then it is likely because you did not specify a value for your enum.
For example, change this:
public enum AcquisitionChannel
{
Referal,
SearchEngines,
SocialMedia
}
to
public enum AcquisitionChannel
{
Referral = 1,
SearchEngines = 2,
SocialMedia = 3
}
If I understand this question correctly why not just use a switch case?
public CaseOriginCode setCaseOriginCode(string caseOriginCodeParam)
{
switch(caseOriginCodeParam)
{
case "Web":
return CaseOriginCode.Web;
case "Email":
return CaseOriginCode.Email;
case "Telefoon":
return CaseOriginCode.Telefoon;
default:
return default(CaseOriginCode);
}
}
So in practice it would be something like this...
int x = (int)setCaseOriginCode("Web"); // output would be 0
CaseOriginCode y = setCaseOriginCode("Email"); // output would be CaseOriginCode.Email
To give some background I'm trying to solve the Project Euler Problem 54 involving poker hands. Though there's infinite approaches to this. What I would like to do is enumerate through a list of strings, for example:
{ "8C", "TS", "KC", "9H", "4S" };
I would like to "get" an instance of class card with properties value, and suit, for each respective string. I've not yet utilized get/set so maybe there is an obvious approach to this I'm missing.
Ultimately I would like to have a list of objects type Card, I don't mind building all the card's ahead of time, such that "2H" returns an instance of type Card where suit = Hearts, and value = 2, for example.
I know this code is wrong, but it should give an idea of what I'm trying to do. Any suggestions would be appreciated.
class Card
{
public string suit;
public int value;
public string cardname
{
get
{
if (cardname == "2H") Card TwoH = new Card();
TwoH.suit = "Hearts"
TwoH.value = 2;
return TwoH;
}
}
}
Why not make a constructor that fills suit and value based on a string parameter
public Card(string name)
{
switch(name)
{
case "2H":
this.suit = "Hearts";
this.value = 2;
break;
//...
}
}
This might not be the exact solution you seem to be asking for but if the values you'll be getting (eg 2H, 3C etc) are all 2 characters long, then you can try this:
public class Card
{
public string suit { get; set; }
public int value { get; set; }
public static Card GetCard(string cardName)
{
string tmpSuit;
int tmpValue;
char[] cardNameParts = cardName.ToCharArray();
switch(charNameParts[0])
{
case "A":
tmpValue = 1;
break;
case "2":
tmpValue = 2;
break;
...
}
switch(charNameParts[1])
{
case "H":
tmpSuit= "Hearts";
break;
case "C":
tmpSuit= "Clubs";
break;
...
}
return new Card() { suit = tmpSuit, value = tmpValue };
}
}
I would do it like that:
public class Card
{
public string Suit { get; set; }
public int Value { get; set; }
public static Card FromString(string s)
{
if (s == "2H") return new Card() { Suit = "Hearts", Value = 2 };
else if (s == "....")
...
else return null;
}
}
I have converted your suit and value field into properties and instead of some getter method which in your case wouldn't work I have added a static method.
You can use it like this Card card2H = Card.FromString("2H");
Maybe use two switch statements, first
switch (cardname[0])
{
...
}
then
switch (cardname[1])
{
...
}
Before that, check that cardname.Length == 2. In each switch, have a default section where you throw an exception in case the char value doesn't make sense.
Say I have a list of member, each of which is a custom object:
public class pail
{
public string milk;
public string water;
public string butter;
public string beer;
}
public class AddToPail()
{
private List<pail> _pailList = new List<pail>();
PSVM(String[] args)
{
for(int i = 0; i < 200; i++)
{
pail newPail = new Pail();
switch(i)
{
case 1:
{
newPail.milk = "This pail has milk";
}
break;
case 2:
{
newPail.butter = "This pail has butter";
}
break;
case 3:
{
newPail.water = "This pail has water";
}
break;
case 4:
{
newPail.beer = "This pail has beer";
}
break;
}
_pailList.Add(newPail);
}
foreach (pail thisPail in _pailList)
{
using (StreamWriter SW = new StreamWriter(#"C:\pail.txt")
{
if (!thisPail.milk.IsNullOrEmpty())
{
SW.WriteLine(thisPail.milk);
}
else if (!thisPail.butter.IsNullOrEmpty())
{
SW.WriteLine(thisPail.butter);
}
else if (!thisPail.beer.IsNullOrEmpty())
{
SW.WriteLine(thisPail.beer);
}
else if (!thisPail.water.IsNullOrEmpty())
{
SW.WriteLine(thisPail.water);
}
else
{
Console.Writeline("oops");
}
}
}
}
}
Say I want to set up a StreamWriter that only prints the true values without having to write a million if, else if, else statements... is there an easy way or library to do this in C#? I'm basically looking for a way to only print out true values in a neat, concise way. Does anyone have any advice as to how I should approach this?
Thank you very much!
EDIT
So the ultimate goal of this is that I have an object that has around 20 members. The object is automatically populated, and the populating script can leave some of the members empty. I'd like to be able to print the members in a CSV format, and not have to have 20 if statements to see if a particular member in the object has been instantiated before outputting via the streamwriter.
Edit 2
I changed my code to be a little closer to what I needed it to do. Sorry for the previous poor explanation.
I think you should refactor your program a little bit. For starters, I would use an enum for bucket contents:
public enum EBucketContents { Milk, Water, Butter, Beer };
Then, instead of having a list of booleans, you can use a dictionary:
var pail = Dictionary<EBucketContents,bool>();
Now it's a simple matter to only output the ones that are true:
foreach( var kvp in pail.Where( x => x.Value ) ) {
SW.WriteLine( "pail has " + kvp.Key.ToString().ToLower() )
}
If you just want to save some typing, use this extension method:
internal static class Extensions
{
public static void WriteLineIf(this TextWriter tw, bool condition, string text)
{
if (condition)
{
tw.WriteLine(text);
}
}
}
But it looks like only one of those bools can be true, since you're using else if blocks.
In that case, use and enum
internal enum Pail
{
Butter,
Milk,
Water,
Beer
}
Can you just use a Dictionary where the key is the field name and the value is the fields value. This way you don't need to check if the output is filled or not - you just output all fields
Your populating script can populate the dictionary keys only if they are set
Then your streamwriter can just go
foreach(KeyValuePair<string, string> kvp in fieldsDict)
sw.Write("Key: " + kvp.Key + ", Value: " + kvp.Value);
Or even just a list of string/or enum
e.g.
public class pail
{
public List<string> Fields = new List<string>();
}
public class AddToPail()
{
private List<pail> _pailList = new List<pail>();
PSVM(String[] args)
{
for(int i = 0; i < 200; i++)
{
pail newPail = new Pail();
switch(i)
{
case 1:
{
newPail.Fields.Add("This pail has milk");
}
break;
*** SNIP
Of course using a Dictionary could solve your problem , but I'm not really fond of this kind of solution, since it makes you lose some control over what you are putting in, e.g you could end up with a pail having airplanes... I'd refactor your code in something like this, trying to give every class its own responsabilities (BTW I don't like AddToPail as a class name, it's more a method name):
public class Pail
{
public string milk;
public string water;
public string butter;
public string beer;
private bool everythingEmpty = true;
public Pail(int i)
{
switch(i)
{
case 1:
{
milk = "This pail has milk";
everythingEmpty = false;
}
break;
case 2:
{
butter = "This pail has butter";
everythingEmpty = false;
}
break;
case 3:
{
water = "This pail has water";
everythingEmpty = false;
}
break;
case 4:
{
beer = "This pail has beer";
everythingEmpty = false;
}
break;
}
}
public void WriteToStream(StreamWriter SW)
{
if (everythingEmpty)
{
Console.Writeline("oops");
return;
}
WriteToStream(milk, SW);
WriteToStream(butter, SW);
WriteToStream(beer, SW);
WriteToStream(water, SW);
}
public static void WriteToStream(string content, StreamWriter SW)
{
if (!content.IsNullOrEmpty())
{
SW.WriteLine(content);
}
}
}
public class AddToPail()
{
private List<pail> _pailList = new List<pail>();
PSVM(String[] args)
{
for(int i = 0; i < 200; i++)
{
pail newPail = new Pail(i);
_pailList.Add(newPail);
}
foreach (pail thisPail in _pailList)
{
using (StreamWriter SW = new StreamWriter(#"C:\pail.txt")
{
thisPail.WriteToStream(SW);
}
}
}
}
I use class Card which contains 2 enumerated properties (suite - hearts diamonds spades and clubs) and card value from 2 to A. And overrides ToString() method to returns something like Ah Ad etc. All ok, but enum value can't starts with number, therefore my card value enumerated looks like x2, x3, x4 ... it is not beautiful.
Also need simple approach to parse few cards from single string.
Who know the best approach to design this class?
Couldn't you assign Jack, Queen, King, and Ace to be 11, 12, 13, and 14, respectively? It'd end up looking something like:
public class Card
{
public int Value { get; private set; }
public enum SuitType
{
Clubs, Spades, Hearts, Diamonds
}
public SuitType Suit { get; private set; }
public Card(int value, SuitType suit)
{
Suit = suit;
Value = value;
}
public Card(string input)
{
if (input == null || input.Length < 2 || input.Length > 2)
throw new ArgumentException();
switch (input[0])
{
case 'C': case 'c':
Suit = SuitType.Clubs;
break;
case 'S': case 's':
Suit = SuitType.Spades;
break;
case 'H': case 'h':
Suit = SuitType.Hearts;
break;
case 'D': case 'd':
Suit = SuitType.Diamonds;
break;
default:
throw new ArgumentException();
}
int uncheckedValue = (int)input[1];
if (uncheckedValue > 14 || uncheckedValue < 1)
throw new ArgumentException();
Value = uncheckedValue;
}
public string encode()
{
string encodedCard = "";
switch (Suit)
{
case SuitType.Clubs:
encodedCard += 'c';
break;
case SuitType.Spades:
encodedCard += 's';
break;
case SuitType.Hearts:
encodedCard += 'h';
break;
case SuitType.Diamonds:
encodedCard += 'd';
break;
}
encodedCard += (char) Value;
return encodedCard;
}
public override string ToString()
{
string output = "";
if (Value > 10)
{
switch (Value)
{
case 11:
output += "Jack";
break;
case 12:
output += "Queen";
break;
case 13:
output += "King";
break;
case 14:
output += "Ace";
break;
}
}
else
{
output += Value;
}
output += " of " + System.Enum.GetName(typeof(SuitType), Suit);
return output;
}
}
Edit:
I added some string functionality.
I took structure of Card(string input) from Jon Hanna's answer.
There's an obvious numeric value for the pip-cards, and we can add J=11, Q=12, K=13.
It may be more convenient to have A=14 than A=1 depending on the game being modelled (so one can more simply compute different relative values of hands).
Enums gives no real advantage, especially since enums allow out-of-range values unless you explicitly check for them (e.g. there is nothing to stop someone assigning (CardValue)54 to the card-value enumeration value).
ToString can be aided with an array of the values {null,"1","2","3","4","5","6","7","8","9","10","J","Q","K"}. Likewise {'♥','♦','♠','♣'} could give a nicer output.
Parsing always trickier than outputting a string, even if you are very strict in what you accept, as you have to deal with the potential for invalid input. A simple approach would be:
private Card(string input)
{
if(input == null)
throw new ArgumentNullException();
if(input.length < 2 || input.length > 3)
throw new ArgumentException();
switch(input[input.Length - 1])
{
case 'H': case 'h': case '♥':
_suit = Suit.Hearts;
break;
case 'D': case 'd': case '♦':
_suit = Suit.Diamonds;
break;
case 'S': case 's': case '♠':
_suit = Suit.Spades;
break;
case 'C': case 'c': case '♣':
_suit = Suit.Clubs;
break;
default:
throw new ArgumentException();
}
switch(input[0])
{
case "J": case "j":
_cardValue = 11;
break;
case "Q": case "q":
_cardValue = 12;
break;
case "K": case "k":
_cardValue = 13;
break;
case "A": case "a":
_cardValue = 1;
break;
default:
if(!int.TryParse(input.substring(0, input.Length - 1), out _cardValue) || _cardValue < 2 || _cardVaue > 10)
throw new ArgumentException;
break;
}
}
public static Card Parse(string cardString)
{
return new Card(cardString);
}
You might want to add a static method that read a larger string, yield returning cards as it parsed, to allow for easier encoding of several cards.
When I first started on the card.dll, I was using enumerations for suits and card rankings but then I didn't want to have to deal with that same issue and writing extra code to compensate for the strings, there for I wrote a abstract class Info with only two variables
(Flag (byte)) and (Name(string)) to be implemented by the Rank class and Suit class which would be members of the Card class. I have found this to work a lot better for naming conventions and filtering purposes. I love using enums but having to work around variable naming can be a hassle so sometimes it is best not to if you have to get the variable name as string.
So when the Card constructor get called the card ID is entered and then it passes into the Rank and Suit which will then separate what the ID means in code (101 = 100 (suit flag) +
1 (rank flag)). The protected abstract SetName(int cardID) and SetFlag(int cardID) while handle the rest from there in the info's constructor via Rank and Suit. No more issues with the enumeration and it can still be filtered by number via the Flag.
This card naming system uses a 1 through 4 * 100 (telling the suit flag) + 1 through 13 (for card rank). 500 + 14 through 16 are Little Joker, Big Joker, and Wild.
public class Card
{
short id;
public Card(string zFile)
{
this.id = Convert.ToInt16(zFile.Split('.')[0].Trim());
this.Rank = new Rank(id);
this.Suit = new Suit(id);
}
public override string ToString()
{
if (Suit.Flag == 5)
return Suit.Name;
return string.Concat(Rank.Name, " of ", Suit.Name);
}
public override int GetHashCode()
{
return id;
}
public Rank Rank { get; private set; }
public Suit Suit { get; private set; }
public static Card GetGreaterRank(Card value1, Card value2)
{
return (value1.Rank >= value2.Rank) ? value1 : value2;
}
public static bool CompareRank(Card value1, Card value2)
{
return (value1.Rank.Flag == value2.Rank.Flag);
}
public static bool CompareSuit(Card value1, Card value2)
{
return (value1.Suit.Flag == value2.Suit.Flag);
}
};
public abstract class Info
{
protected Info(short cardID)
{
Flag = SetFlag(cardID);
}
protected string SetName(short cardID, params string[] names)
{
for (int i = 0; i < names.Length; i++)
{
if (Flag == (i + 1))
return names[i];
}
return "Unknown";
}
protected abstract byte SetFlag(short cardID);
public static implicit operator byte(Info info)
{
return info.Flag;
}
public byte Flag { get; protected set; }
public string Name { get; protected set; }
};
public class Rank : Info
{
internal Rank(short cardID) : base(cardID)
{
string name = SetName(cardID, "A","2","3","4","5","6","7",
"8","9","10","J","Q","K","Little Joker","Big Joker","Wild");
Name = (name == "Unknown") ? string.Concat(name, " Rank") : name;
}
protected override byte SetFlag(short cardID)
{
return Convert.ToByte(cardID.ToString().Remove(0, 1));
}
};
public class Suit : Info
{
internal Suit(short cardID) : base(cardID)
{
string name = SetName(cardID,"Clubs","Diamonds","Hearts","Spades");
Name = (name == "Unknown") ? string.Concat(name, " Suit") ? name;
}
protected override byte SetFlag(short cardID)
{
return Convert.ToByte(cardID.ToString().Remove(1));
}
};
So now if you have your card image file named 101.png and pass it into the Card ctor it will pass to the Rank and Suit getting the info for you. Really all you are doing in giving the image file a code(numeric) for a name.
I would probably start out with 2 enums, 1 representing the Suits and 1 representing the Faces. Then declare a public property "Suit" and a public property "Face" based off of these enums. You will also probably need an array with the different unique values that a card can have (i.e. 1 throught 13).
You can start enums with number (although it is preferred to start at zero)
public enum Card
{
Two = 2,
Three,
Four,
...
}
Scratch what I wrote before, this is better.
using System;
enum Suit
{
Clubs,
Hearts,
Diamonds,
Spades
}
class Card
{
Suit Suit
{
get;
private set;
}
int Value
{
get;
private set;
}
Card(Suit suit, int value)
{
Suit = suit;
Value = value;
}
private const string[] valsToString = new string[] { "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A" };
bool IsValid()
{
return Value >= 2 && Value <= 14;
}
override string ToString()
{
return string.Format("{0} of {1}", valsToString[Value - 2], Suit);
}
}