Some parts I don't understand - c#

C# code:
using System;
// this is the delegate declaration
public delegate int Comparer(object obj1, object obj2);
public class Name
{
public string FirstName = null;
public string LastName = null;
public Name(string first, string last)
{
FirstName = first;
LastName = last;
}
// this is the delegate method handler
public static int CompareFirstNames(object name1, object name2)
{
string n1 = ((Name)name1).FirstName;
string n2 = ((Name)name2).FirstName;
if (String.Compare(n1, n2) > 0)
{
return 1;
}
else if (String.Compare(n1, n2) < 0)
{
return -1;
}
else
{
return 0;
}
}
public override string ToString()
{
return FirstName + " " + LastName;
}
}
class SimpleDelegate
{
Name[] names = new Name[5];
public SimpleDelegate()
{
names[0] = new Name("Joe", "Mayo");
names[1] = new Name("John", "Hancock");
names[2] = new Name("Jane", "Doe");
names[3] = new Name("John", "Doe");
names[4] = new Name("Jack", "Smith");
}
static void Main(string[] args)
{
SimpleDelegate sd = new SimpleDelegate();
// this is the delegate instantiation
Comparer cmp = new Comparer(Name.CompareFirstNames);
Console.WriteLine("\nBefore Sort: \n");
sd.PrintNames();
// observe the delegate argument
sd.Sort(cmp);
Console.WriteLine("\nAfter Sort: \n");
sd.PrintNames();
}
// observe the delegate parameter
public void Sort(Comparer compare)
{
object temp;
for (int i=0; i < names.Length; i++)
{
for (int j=i; j < names.Length; j++)
{
// using delegate "compare" just like
// a normal method
if ( compare(names[i], names[j]) > 0 )
{
temp = names[i];
names[i] = names[j];
names[j] = (Name)temp;
}
}
}
}
public void PrintNames()
{
Console.WriteLine("Names: \n");
foreach (Name name in names)
{
Console.WriteLine(name.ToString());
}
}
}
There are two parts of the code that I don't understand at all. What do these parts exactly do, (respectively); and what subject(s) do I need to learn to understand these parts?
string n1 = ((Name)name1).FirstName;
What does ((Name)name1) do?
public void Sort(Comparer compare)
Can anyone provide any tips or feedback on how those parts of the code function? Can you possibly lead me into the right direction?

First: string n1 = ((Name)name1).FirstName
(Name)name1 which can be written generically as (Type)variable. What this does is take the variable and attempt to cast (a synonym would be convert) the variable name1 into the type Name. This then allows us to access the FirstName property.
Learn more here: https://www.w3schools.com/cs/cs_type_casting.asp
Second: public void Sort(Comparer compare)
This is a method declaration.
public indicates the accessibility. Other options include private, protected and a few others. public indicates that this method can be called by any code that has a reference to an instance of this object.
void indicates the return type. void is a special keyword to mean that no value is returned from the method.
Sort is the method name
Compare compare: Compare is the type of the parameter to be passed in and compare is the name of the parameter which can be used throughout the method.
Learn more here: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/methods

Related

Cannot implicitly convert type void to string

class Program
{
static void Main(string[] args)
{
List<string> itemsNames = new List<string>();
List<decimal> itemsPrices = new List<decimal>();
itemsNames.Add("Bread");
itemsNames.Add("Milk");
itemsNames.Add("Juice");
itemsNames.Add("Chocolate");
itemsNames.Add("Cheese");
itemsNames.Add("Ham");
itemsNames.Add("Chicken");
itemsPrices.Add(2.50M);
itemsPrices.Add(3.00M);
itemsPrices.Add(4.50M);
itemsPrices.Add(1.50M);
itemsPrices.Add(2.50M);
itemsPrices.Add(3.50M);
itemsPrices.Add(13.50M);
string result = CombineTheLists(itemsNames, itemsPrices);
Console.WriteLine("\r\nPress enter to continue...");
Console.ReadKey();
}
public static void CombineTheLists(List<string> itemNames, List<decimal> itemPrices)
{
for (int i = 0; i < itemNames.Count; i++)
{
string result = "";
string names = itemNames[i];
decimal prices = itemPrices[i];
Console.WriteLine($"The {names} costs ${prices}");
}
}
I've been trying to figure the proper way to make the function call to the method I created in the code provided. When I attempt to make the function call it just shows the cannot convert void to string error and I know it's because the method I created is and must be void. Is there a work around my issue?
If you want your function to return something, it should not be void. If you don't want it to return something, string result = is not necessary. You have to decide what you really need. (EDIT: Looks like you already did, and other answers covered this very well). Also instead of holding those two lists, you should create a class or struct to your items:
public class Item
{
public string Name { get; set; }
public decimal Price{ get; set; }
public Item(string name, decimal price)
{
Name = name;
Price = price;
}
}
And use it like this:
static void Main(string[] args)
{
List<Item> items = new List<Item>();
items.Add(new Item("Bread", 2.50M));
items.Add(new Item("Milk", 3.00M));
items.Add(new Item("Juice", 4.50M));
items.Add(new Item("Chocolate", 1.50M));
items.Add(new Item("Cheese", 2.50M));
items.Add(new Item("Ham", 3.50M));
items.Add(new Item("Chicken", 13.50M));
string result = PrintList(itemsNames, itemsPrices);
Console.WriteLine("\r\nPress enter to continue...");
Console.ReadKey();
}
public static string PrintList(List<Item> items)
{
var stringBuilder = new StringBuilder();
for (int i = 0; i < items.Count; i++)
{
string names = items[i].Name;
decimal prices = items[i].Price;
sb.AppendLine($"The {names} costs ${prices}");
}
return sb.ToString();
}
This will make your life much easier.
EDIT2: Other ways to loop through the list:
foreach:
foreach(Item i in items)
{
string name = i.Name;
decimal price = i.Price;
}
while:
int i = 0;
while(i < items.Count)
{
string name = items[i].Name;
decimal price = items[i].Price;
i++;
}
CombineTheLists does not return anything, but you're trying to assign it to a string:
string result = CombineTheLists(itemsNames, itemsPrices);
Change it to return a string (and, obviously return it, instead of using Console.WriteLine) or dont try to capture the return if you did want to just write to the console.
CombineTheLists(itemsNames, itemsPrices);
As an alternative if you were tryingg to build a string inside the method, and return it you could use a StringBuilder:
public static string CombineTheLists(List<string> itemNames, List<decimal> itemPrices)
{
var sb = new StringBuidler();
for (int i = 0; i < itemNames.Count; i++)
{
string result = "";
string names = itemNames[i];
decimal prices = itemPrices[i];
sb.AppendLine($"The {names} costs ${prices}");
}
return sb.ToString();
}
Note that I changed the return type to string - you can then call it as your original code
string result = CombineTheLists(itemsNames, itemsPrices);
Console.WriteLine(result);
Change the return type of your function
public static string CombineTheLists(List<string> itemNames, List<decimal> itemPrices)
{
for (int i = 0; i < itemNames.Count; i++)
{
string result = "";
string names = itemNames[i];
decimal prices = itemPrices[i];
Console.WriteLine($"The {names} costs ${prices}");
}
return "somestring from CombineTheLists function";
}
or
Don't expect from the function it will return string and make a simple call to the function.
When you call it with this line:
string result = CombineTheLists(itemsNames, itemsPrices);
you are taking the result of the CombineTheLists method and trying to convert its result to a string, storing the result in a variable called result.
You are not actually using the result variable, so you needn't create it in the first place.
More importantly, the return type of CombineTheLists is explicitly void:
public static void CombineTheLists(List<string> itemNames, List<decimal> itemPrices)
and as the method does not include a return statement, it does not return a string either.
To fix this you simply need to do this instead:
static void Main(string[] args)
{
List<string> itemsNames = new List<string>();
List<decimal> itemsPrices = new List<decimal>();
itemsNames.Add("Bread");
itemsNames.Add("Milk");
itemsNames.Add("Juice");
itemsNames.Add("Chocolate");
itemsNames.Add("Cheese");
itemsNames.Add("Ham");
itemsNames.Add("Chicken");
itemsPrices.Add(2.50M);
itemsPrices.Add(3.00M);
itemsPrices.Add(4.50M);
itemsPrices.Add(1.50M);
itemsPrices.Add(2.50M);
itemsPrices.Add(3.50M);
itemsPrices.Add(13.50M);
string result = CombineTheLists(itemsNames, itemsPrices);
Console.Write(result);
Console.WriteLine("\r\nPress enter to continue...");
Console.ReadKey();
}
public static string CombineTheLists(List<string> itemNames, List<decimal> itemPrices)
{
var stringBuilder = new StringBuilder();
for (int i = 0; i < itemNames.Count; i++)
{
string names = itemNames[i];
decimal prices = itemPrices[i];
stringBuilder.AppendLine($"The {names} costs ${prices}");
}
return stringBuilder.ToString();
}

Using enum item to call a method

I have an enum with 30 items in it. Each item has a corresponding function with the same name. I would like to be able to call the function by referencing the enum at a certain position.
So if the value at enum[0] = Foo, I would like to be able to call Foo(string bar) by using something like enum(0)("foobar")
In the end the point is I am running each function as a task like so:
enum Test { AA, BB, CC, DD ....}
tasks[0] = Task.Run(() => { prices[0] = AA("a string"); });
tasks[1] = Task.Run(() => { prices[1] = BB("a string"); });
tasks[2] = Task.Run(() => { prices[2] = CC("a string"); });
//for 30 tasks
What I would like to do is something along the lines of:
enum Test { AA, BB, CC, DD ....}
for (int i = 0; i < 30; i++)
{
tasks[i] = Task.Run(() => { prices[i] = (Test)i("a string"); });
}
Task.WaitAll(tasks.ToArray());
Is this something that is even possible?
EDIT:
The enum relates to controls on a form so i have an array of textboxs, label and a array of prices that is populated with the results of the functions:
enum Dealers { Dealer1, Dealer2 ... Dealer29, Dealer30 };
static int noOfDealers = Enum.GetNames(typeof(Dealers)).Length;
decimal[] prices = new decimal[noOfDealers];
TextBox[] textBox = new TextBox[noOfDealers];
Label[] boxes = new Label[noOfDealers];
for (int i = 0; i < noOfDealers; i++)
{
textBox[i] = Controls.Find("txt" + (Dealers)i, true)[0] as TextBox;
boxes[i] = Controls.Find("box" + (Dealers)i, true)[0] as Label;
prices[i] = 0;
}
//RUN 30 TASKS TO POPULATE THE PRICES ARRAY
for (int i = 0; i < noOfDealers; i++)
{
textBox[i].Text = "£" + prices[i].ToString();
}
//LOOP THROUGH PRICES ARRAY AND FIND CHEAPEST PRICE, THEN COLOUR THE LABEL BACKGROUND GREEN FOR THE TEXT BOX WITH THE NAME AT ENUM VALUE WHATEVER I IS
I guess i am just trying to make my code as concise as possible, there is the potential for the amount of tasks to double and didn't want to end up with 60 lines to populate the tasks array
I would create dictionary and map enum to actions:
Dictionary<Test, Func<string,double>> actions = new Dictionary<Test, Func<string,double>>()
{
{Test.AA, (x) => { return 5;}},
{Test.BB, (x) => { return 15; }},
}; //x is your string
var res = actions[Test.AA]("hello");
I would strongly suggest using a built in construct - like an extension method and a simple switch:
public static int GetPriceWithString(this Test test, string str)
{
switch (test)
{
case Test.AA:
break;
case Test.BB:
break;
case Test.CC:
break;
case Test.DD:
break;
default:
throw new ArgumentOutOfRangeException(nameof(test), test, null);
}
}
then your loop looks almost the same:
for (int i = 0; i < 30; i++)
{
tasks[i] = Task.Run(() =>
{
prices[i] = ((Test)i).GetPriceWithString("a string");
});
}
What you want to do is possible with reflection, which can be a powerful tool - but ideally should only be used as a last resort, as it will hide what could be compile time errors, and cause less code readability.
Using a simple switch like this makes your code self-documented, so when you come back to this in a month you can quickly remember what the intention was.
How about using an array of delegates:
using System;
using System.Threading.Tasks;
namespace ConsoleApplication
{
class Program
{
private static int AA(string a) { return 0; }
private static int BB(string a) { return 1; }
private static int CC(string a) { return 2; }
private static Func<string, int>[] functions = new Func<string, int>[] { AA, BB, CC };
private static int[] prices = new int[functions.Length];
private static Task[] tasks = new Task[functions.Length];
static void Main(string[] args)
{
for (int i = 0; i < functions.Length; ++i)
tasks[i] = Task.Run(() => { prices[i] = functions[i]("a string"); });
Task.WaitAll(tasks);
}
}
}
An eg. speaks a lot more than words.
I used it in a winform so the this refers to win form.
I have assumed all your methods are public , have same signature & return the same type.
enum MyName { AA,BB,CC};
//Call this in one of your methods
string [] strVal= Enum.GetNames(typeof(MyName));
int x = CallFunction(strVal[0], "A");
int y = CallFunction(strVal[1], "h");
int z = CallFunction(strVal[1], "C");
//End Call this in one of your methods
int CallFunction(string strName,string strValue)
{
return Convert.ToInt32(this.GetType().InvokeMember(strName, BindingFlags.Public | BindingFlags.InvokeMethod|BindingFlags.Instance, null, this, new object[] { strValue }));
}
public int AA(string s)
{
return 1;
}
public int BB(string s)
{
return 2;
}
public int CC(string s)
{
return 3;
}
Another solution. I hope somebody will consider it as overkill :)
Create abstract class DealerBase.
public abstract class DealerBase
{
public string Name { get; }
public decimal Price { get; set; }
protected DealerBase(string name)
{
Name = name;
}
public abstract void UpdatePrice();
}
Then create classes for every dealers you have and implement own logic for UpdatePrice method.
public class Dealer1 : DealerBase
{
public Dealer1() : base("DealerOne") { }
public override void UpdatePrice()
{
//Calculate price
Price = DealerOneCalculationMethod();
}
}
public class Dealer2 : DealerBase
{
public Dealer2() : base("DealerTwo") { }
public override void UpdatePrice()
{
//Calculate price
Price = DealerTwoCalculationMethod();
}
}
And so on..
Then you just create collection of dealers which can be easily iterated
var dealers = new List<DealerBase>
{
new Dealer1(),
new Dealer2()
}
foreach(var dealer in dealers)
{
dealer.UpdatePrice();
}
You can loop dealers and generate textboxes, labels in the winforms.
But I suggest to use DataGridView where code will be tiny clearer.
First implement INotifyPropertyChanged interface in the base class DealerBase
public abstract class DealerBase : INotifyPropertyChanged
{
public string Name { get; }
protected decimal _Price;
public decimal Price
{
get { return _Price; }
set
{
if (Equals(_Price, value)) return;
_Price = value;
// next method will inform DataGridView about changes
// and update value there too
RaisePropertyChanged();
}
protected DealerBase(string name)
{
Name = name;
}
public abstract void UpdatePrice();
// Implementation of INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
The in the Form you can create BindingList<DealerViewModelBase> and set it to DataGridView.DataSource
public class YourForm: Form
{
public YourForm()
{
InitializeComponent();
var dealers = new List<DealerBase>
{
new Dealer1(),
new Dealer2()
};
var bindSource = new BindingList<DealerBase>(dealers);
dataGridView.DataSource = bindSource;
}
// Add button which update prices for all dealers
private void ButtonUpdatePrices_Click(object sender, EventArgs e)
{
var dealers = (BindingList<DealerBase>)dataGridView.DataSource;
foreach (var dealer in dealers)
{
dealer.UpdatePrice();
// Because we call `RaisePropertyChanged` in
// setter of Price - prices will be automatically
// updated in DataGridView
}
}
}
Idea of this approach you put different logic of different dealers in the separated class which. Because all dealer classes will inherit from same abstract class you can add different dealers to the collection.
You already have hardcoded enums and correspondent method which you try to link together. This approach make using of dealers collection little bid easy

Abstract Factory Pattern Default Class Issue

Hi,
I've a class which has a method with some condition checks and append a string according to condition. I tried to refactor this code with abstract factory pattern.
My problem is related to default expression class. If none of other rules applies to related filter, then I want to apply default expression rule. However on my application; it depends the order of StandartExpression instance order in the _expressions list. If it is added first then the other rules will not be checked.
I think I missed something about that pattern. Could you help me?
This is my application code:
public class Filter
{
private string _operator = "="; // =, !=, <,> ...
public string Name { get; set; }
public object Value { get; set; }
public string Operator { get { return _operator; } set { _operator = value; } }
}
Filter filter = null;
StringBuilder whereClause = new StringBuilder();
for (int i = 0; i < array.Length; i++)
{
filter = array[i];
if (filter.Value.ToString().ToLower().Equals("null"))
{
whereClause.Append(filter.Name + " " + filter.Operator + " null ");
}
else if (filter.Operator.ToLower().Equals("like"))
{
whereClause.Append(filter.Name + ".Contains(#" + i + ")");
}
else
{
whereClause.Append(filter.Name + " " + filter.Operator + " #" + i);
}
whereClause.Append(" AND ");
}
Now, this is the abstract factory pattern code:
public interface ICustomExpression
{
bool ExpressionIsValid(Filter filter);
string GetExpressionStr(Filter filter, int index);
}
public class StandardExpression : ICustomExpression
{
public bool ExpressionIsValid(Filter filter)
{
return true;
}
public string GetExpressionStr(Filter filter, int index)
{
return filter.Name + " " + filter.Operator + " #" + index;
}
}
public class LikeExpression : ICustomExpression
{
public bool ExpressionIsValid(Filter filter)
{
return filter.Operator.ToLower().Equals("like");
}
public string GetExpressionStr(Filter filter, int index)
{
return filter.Name + ".Contains(#" + index + ")";
}
}
public class NullExpression : ICustomExpression
{
public bool ExpressionIsValid(Filter filter)
{
return filter.Value.ToString().ToLower().Equals("null");
}
public string GetExpressionStr(Filter filter, int index)
{
return filter.Name + " " + filter.Operator + " null ";
}
}
public static class ExpressionFactory
{
private static List<ICustomExpression> _expressions = null;
public static List<ICustomExpression> Expressions
{
get
{
if (_expressions == null)
{
Build();
}
return _expressions;
}
}
private static void Build()
{
_expressions = new List<ICustomExpression>();
_expressions.Add(new NullExpression());
_expressions.Add(new LikeExpression());
_expressions.Add(new StandardExpression());
}
}
And that is how I used that structure on my application code:
StringBuilder whereClause = new StringBuilder();
Filter filter = null;
var array = filterList.ToArray();
for (int i = 0; i < array.Length; i++)
{
filter = array[i];
foreach (ICustomExpression exp in ExpressionFactory.Expressions)
{
if (exp.ExpressionIsValid(filter))
whereClause.Append(exp.GetExpressionStr(filter, i));
}
whereClause.Append(" AND ");
}
Your feeling is right: there is a hidden distinction between "special" and "standard" expressions that should be made explicit for clarity.
However, in my eyes the bigger problem is that your factory is not actually handling the type selection and instantiation on its own but is delegating parts of that responsibility to its clients. Every client has to know how to work with the collection property Expressions and thus also has to know about this implicit distinction I mentioned above.
Ideally clients of the ExpressionFactory should just hand it a filter in order to get the correct ICustomExpression instance. Here's how this might look like:
public static class ExpressionFactory
{
private static StandardExpression _standardExpression = new StandardExpression();
private static ICustomExpression[] _specialExpressions = new []
{
(ICustomExpression)new NullExpression(),
(ICustomExpression)new LikeExpression()
};
public static ICustomExpression GetBy(Filter filter)
{
var match = _specialExpressions.SingleOrDefault(e => e.ExpressionIsValid(filter));
if (match == null)
return _standardExpression;
return match;
}
}
The rules how an expression is created (or rather selected, in your case) is now only known by the factory and thus implemented in a single place.
I also made the implicit distinction between "special" and "standard" expressions explicit, so the implementation does not depend on the order in which the ICustomExpressions are added anymore.
Note that the usage of the factory now becomes more straight-forward:
for (int i = 0; i < array.Length; i++)
{
filter = array[i];
var exp = ExpressionFactory.GetBy(filter);
whereClause.Append(exp.GetExpressionStr(filter, i));
whereClause.Append(" AND ");
}
Here is a working example of the refactored code: https://dotnetfiddle.net/uzVJhM
By the way: your implementation looks more like an instance of the factory method pattern.

C# custom object in combobox

I am relatively new to C# (WinForms), and had a question regarding combo boxes. I have a combo box of Reviewer objects (it is a custom class with an overridden ToString method) and am currently attempting to go through all the checked items and use them to generate a setup file.
Here is how the combo box is populated (populated on form load). Parameters is just a collection of linked lists and parsing code.
for (int i = 0; i < parameters.GetUsers().Count; i++)
{
UserList.Items.Add(parameters.GetUsersArray()[i], parameters.GetUsersArray()[i].isSelected());
}
Here is how I am trying to read it. setup is a StringBuilder. The problem is that GetID is not defined. Does the add function above cast the Reviewer object to a Object object? It looks a little funny since it creates a file fed into a Perl script. A sample desired output line looks like this: inspector0 => "chg0306",
for (int i = 0; i < UserList.CheckedItems.Count; i++)
{
setup.AppendLine("inspector" + i.ToString() + " => \t \"" +
UserList.CheckedItems[i].GetID() + "\",");
}
Here is the users class: (Sample User is ID = aaa0000 name: Bob Joe)
public class Reviewer
{
private string name;
private string id;
private bool selected;
public Reviewer(string newName, string newID, bool newSelected)
{
name = newName;
id = newID;
selected = newSelected;
}
public string GetName()
{
return name;
}
public override string ToString()
{
//string retVal = new string(' ', id.Length + name.Length + 1);
string retVal = id + '\t' + name;
return retVal;
}
public string GetID()
{
return id;
}
public bool isSelected()
{
return selected;
}
}
For posterity, here is the Parameters class:
public class ParameterLists
{
public ParameterLists()
{
projects = new LinkedList<string>();
reviewers = new LinkedList<Reviewer>();
}
public enum FileContents {
PROJECT_LIST,
USERS_LIST,
}
public LinkedList<Reviewer> GetUsers()
{
return reviewers;
}
public LinkedList<string> GetProjects()
{
return projects;
}
public Reviewer[] GetUsersArray()
{
Reviewer[] userArray = new Reviewer[reviewers.Count];
reviewers.CopyTo(userArray, 0);
return userArray;
}
public string[] GetProjectsArray()
{
String[] projectArray = new String[projects.Count];
projects.CopyTo(projectArray, 0);
return projectArray;
}
public void LoadParameters(string fileName)
{
//Reads the parameters from the input file.
}
private void CreateDefaultFile(string fileName)
{
// Create the file from the defaultfile , if it exists.
// Otherwise create a blank default file.
}
private LinkedList <string> projects;
private LinkedList <Reviewer> reviewers;
}
I am probably missing something simple, coming from embedded C++. Any help would be appreciated.
You have to cast that object:
((Reviewer)UserList.CheckedItems[i]).GetID()

How to remove this duplicate code

I have this same code on two places:
if (amountUnit.ToLower().Contains("x"))
{
string[] amount = amountUnit.Split('x');
x = amount[0].Trim();
y = amount[1].Trim();
}
else
{
x = "1";
y = amountUnit.Trim();
}
//
unit = textInBrackets.Replace(amountUnit, "");
name = "";
for (int z = 0; z < i; z++)
{
name += someArray[z];
name += " ";
}
name = name.Trim();
The exact code is repeated twice. How to fix it? If i extract it in a new method, I'll have a lot of ref input parameters. Is there another way?
If it's not possible, just the part untill the comments?
Like:
public struct Parameters
{
public int X {get; set;}
public int Y {get; set;}
}
public Parameters ExtractParameters(string amountUnit)
{
var parameters = new Parameters();
if (amountUnit.ToLower().Contains("x"))
{
string[] amount = amountUnit.Split('x');
parameters.X = int.Parse(amount[0].Trim());
parameters.Y = int.Parse(amount[1].Trim());
}
else
{
parameters.X = 1;
parameters.Y = int.Parse(amountUnit.Trim());
}
return parameters;
}
Usage:
var parameters = ExtractParameters(amountUnit);
var x = parameters.X;
var y = parameters.Y;
You can also make it an extension method on string.
And of course you best add some exception handling too.
The code seems to have two, separate blocks, logically.
One that deals with x and y - the other with name. These should probably be separate methods.
Now, you can create a type (class or structure) that encapsulates x and y, meaning that you only need to pass in one parameter. Instead of passing it by ref you can simply return it and in the caller replace what you passed in.
Combine your code and your data into a class ;-)
public class Point
{
public Point(string amountUnit)
{
if (amountUnit == null)
{
throw new ArgumentNullException("amountUnit");
}
if (amountUnit.ToLower().Contains("x"))
{
string[] amount = amountUnit.Split('x');
this.X = amount[0].Trim();
this.Y = amount[1].Trim();
}
else
{
this.X = "1";
this.Y = amountUnit.Trim();
}
}
string X { get; private set; }
string Y { get; private set; }
}
If you don't need anything very dynamic, how about splitting it into two methods, and doing something as simple as this:
public static string GetX(string amountUnit)
{
return amountUnit.ToLower().Contains("x") ?
amountUnit.Split('x')[0].Trim() :
"1";
}
public static string GetY(string amountUnit)
{
return amountUnit.ToLower().Contains("x") ?
amountUnit.Split('x')[1].Trim() :
amountUnit.Trim();
}

Categories

Resources