I would like to request what's the best way to handle the situation below.
I would like to call populate function for different instance with different parameters. I implemented populate function in each inheritance classes. But I don't know what's the best way to use it for hundreds of times.
(Eg index would be the total number of country in the world).
public enum TCountry
{
tAustralia,
tUnitedKingdom,
.. etc..
}
public enum TCity
{
tSydney,
tLondon,
... etc..
}
public int ProcessData ( string population, int index)
{
switch (index)
{
case 0:
TypeAust aus = new TypeAust();
retun aus.poulate( population, tAustralia, tSydney);
// Different calculation Sydney -Aus
DisplayAus(); // Display for Sydney - Aus
case 1:
TypeUK uk = new TypeUK();
retun uk.poulate( population, tUnitedKingdom, tLondon);
// Different calculation for Londond - UK
DisplayUK(); // Display for London - UK
....
... etc..
}
}
Thanks in Advance
I would recommend going with a different design. Rather than working with that case statement, put all your types in a collection and call populate without knowing what specific type you're working with.
List<TypeCountry> countries = new List<TypeCountry>() { new TypeUK(), TypeAus(), TypeUS() //ect };
//use this list all throughout the program
Instead of you switch statement you can just do;
return countries[index].populate( //args go here );
Then you can do other things like;
int worldPop = countries.Aggregate((c, n) => c.Populate(//args) + n.Populate(//args));
In general you need to stop treating each type as if it's different from the next. Move your logic into the base class, get rid of code that has to refer to the type by name or requires specific checks for which inheriting type it is. For almost all cases you should be able to have a collection of the base classes type and pass it around and work on it without ever knowing what type the specific instance you're dealing with is. If that's not the case then you're doing inheritance wrong. If you have that big case statement then there is no point in even using inheritance because as far as I can tell you're not getting any of it's benefits.
I would have to see more of your actual needs and architecture but you could look into generics.
public int ProcessData<T>(string population) where T : BaseCountry, new() {
var country = new T();
Display(country);
return country.Populate(population);
}
public void Display<T>(T country) where T : BaseCountry { ... }
You would use ProcessData like:
ProcessData<TypeAust>(99);
Your display method would be generic too. This way, your process data method is always constrained to work with anything that implements BaseCountry. BaseCountry would define an abstract or virtual Populate() method.
You could do something like this so the logic is broken out into different classes:
public enum TCountry
{
tAustralia,
tUnitedKingdom
}
public enum TCity
{
tSydney,
tLondon
}
public abstract class TypeCountry
{
public abstract int Populate(string population);
}
public class TypeAust : TypeCountry
{
public override int Populate(string population)
{
// do your calculation with tAustralia, tSydney...
}
}
public class TypeUK: TypeCountry
{
public override int Populate(string population)
{
// do your calculation with tUnitedKingdom, tLondon...
}
}
public static class TypeCountryFactory
{
public static TypeCountry GetCountry(TCountry country)
{
switch (country)
{
case TCountry.tAustralia:
return new TypeAust();
case TCountry.tUnitedKingdom:
return new TypeUK();
}
}
}
public int ProcessData (string population, int TCountry)
{
TypeCountry country = TypeCountryFactory.GetCountry(TCountry);
return country.Populate(population);
}
Related
I'm creating an app that returns a list of metals to use in various conditions. I have a Metal class then classes for each type of Metal like Steel, Aluminum, etc. If I have a list of different Steels, I want to first select the best ones based on a set of properties common to all Metals then do a second pass based on the unique properties of Steel. (This isn't my exact problem but my problem is analogous.)
I can't figure out how to pass a List<Steel> to the GetBest() method of the Metal class as shown below that takes its first argument of type List<Metal>. The code won't compile due to error at the line highlighted below with **: "Argument 1: cannot convert from 'System.Collections.Generic.List<Steel>' to 'System.Collections.Generic.List<Metal>'.
public class Metal {
public int PropA { get; set; }
public List<Metal> GetBest( List<Metal> list, int condition1 )
{
var best = new List<Metal>();
//Analysis code here...
return best;
}
}
public class Steel : Metal
{
public int PropB { get; set; }
public List<Steel> GetBest(List<Steel> list, int condition1, int condition2 ) {
var bestSteel = new List<Steel>();
//Do first pass selection based on properties of all metals.
**bestSteel = Metal.GetBest(list, condition1);**
//Do some additional analysis based to Steel's unique properties.
//Analysis code here...
return bestSteel;
}
You could use a constrained generic method:
public static List<T> GetBest<T>(List<T> list, int condition1) where T : Metal
{
var best = new List<T>();
// Analysis code here...
return best;
}
I'm going to answer a different question! A look at how I might approach this problem without confounding my objects (Metal, Steel) with my logic for picking the best metal based on some conditions:
public class Metal{}
public class Steel:Metal{}
public class MetalPickerContext
{
public int Condition1{ get;set;}
}
public class MetalPicker<TMetal, TContext>
where TMetal: Metal
where TContext: MetalPickerContext
{
public virtual IEnumerable<TMetal> GetBest(IEnumerable<TMetal> list, TContext context)
{
var result = new List<TMetal>();
// logic for picking the best metal based on Condition1
return result;
}
}
public class SteelPickerContext: MetalPickerContext
{
public int Condition2{get;set;}
}
public class SteelPicker : MetalPicker<Steel,SteelPickerContext>
{
public override IEnumerable<Steel> GetBest(IEnumerable<Steel> list, SteelPickerContext context)
{
var initialResult = base.GetBest(list,context);
// Having called the base logic apply more with reference to Condition2
return initialResult;
}
}
This compiles (as you can see here) and I could expand the example a bit given some more details to make it a working one. Let me know if that would help you.
Say I have a class like this for calculating the cost of travelling different distances with different modes of transportation:
public class TransportationCostCalculator
{
public double DistanceToDestination { get; set; }
public decimal CostOfTravel(string transportMethod)
{
switch (transportMethod)
{
case "Bicycle":
return (decimal)(DistanceToDestination * 1);
case "Bus":
return (decimal)(DistanceToDestination * 2);
case "Car":
return (decimal)(DistanceToDestination * 3);
default:
throw new ArgumentOutOfRangeException();
}
}
This is fine and all, but switch cases can be a nightmare to maintenance wise, and what if I want to use airplane or train later on? Then I have to change the above class. What alternative to a switch case could I use here and any hints to how?
I'm imagining using it in a console application like this which would be run from the command-line with arguments for what kind of transportation vehicle you want to use, and the distance you want to travel:
class Program
{
static void Main(string[] args)
{
if(args.Length < 2)
{
Console.WriteLine("Not enough arguments to run this program");
Console.ReadLine();
}
else
{
var transportMethod = args[0];
var distance = args[1];
var calculator = new TransportCostCalculator { DistanceToDestination = double.Parse(distance) };
var result = calculator.CostOfTravel(transportMethod);
Console.WriteLine(result);
Console.ReadLine();
}
}
}
Any hints greatly appreciated!
You could do something like this:
public class TransportationCostCalculator {
Dictionary<string,double> _travelModifier;
TransportationCostCalculator()
{
_travelModifier = new Dictionary<string,double> ();
_travelModifier.Add("bicycle", 1);
_travelModifier.Add("bus", 2);
_travelModifier.Add("car", 3);
}
public decimal CostOfTravel(string transportationMethod) =>
(decimal) _travelModifier[transportationMethod] * DistanceToDestination;
}
You could then load the transportation type and it's modifier in a configuration file instead of using a switch statement. I put it in the constructor to show the example, but it could be loaded from anywhere. I would also probably make the Dictionary static and only load it once. There is no need to keep populating it each time you create a new TransportationCostCalculator especially if it isn't going to change during runtime.
As noted above, here is how you could load it by a configuration file:
void Main()
{
// By Hard coding.
/*
TransportationCostCalculator.AddTravelModifier("bicycle", 1);
TransportationCostCalculator.AddTravelModifier("bus", 2);
TransportationCostCalculator.AddTravelModifier("car", 3);
*/
//By File
//assuming file is: name,value
System.IO.File.ReadAllLines("C:\\temp\\modifiers.txt")
.ToList().ForEach(line =>
{
var parts = line.Split(',');
TransportationCostCalculator.AddTravelModifier
(parts[0], Double.Parse(parts[1]));
}
);
}
public class TransportationCostCalculator {
static Dictionary<string,double> _travelModifier =
new Dictionary<string,double> ();
public static void AddTravelModifier(string name, double modifier)
{
if (_travelModifier.ContainsKey(name))
{
throw new Exception($"{name} already exists in dictionary.");
}
_travelModifier.Add(name, modifier);
}
public double DistanceToDestination { get; set; }
TransportationCostCalculator()
{
_travelModifier = new Dictionary<string,double> ();
}
public decimal CostOfTravel(string transportationMethod) =>
(decimal)( _travelModifier[transportationMethod] * DistanceToDestination);
}
Edit: It was mentioned in the comments that this wouldn't allow the equation to be modified if it ever needed to change without updating the code, so I wrote up a post about how to do it here: https://kemiller2002.github.io/2016/03/07/Configuring-Logic.html.
It looks to me like any solution based on your current method is flawed in one critical way: No matter how you slice it, you're putting data in your code. This means every time you want to change any of these numbers, add a new vehicle type, etc., you have to edit code, and then recompile, distribute a patch, etc.
What you really should be doing is putting that data where it belongs - in a separate, non-compiled file. You can use XML, JSON, some form of database, or even just a simple config file. Encrypt it if you want, not necessarily needed.
Then you'd simply write a parser that reads the file and creates a map of vehicle type to cost multiplier or whatever other properties you want to save. Adding a new vehicle would be as simple as updating your data file. No need edit code or recompile, etc. Much more robust and easier to maintain if you plan to add stuff in the future.
Sounds like a good candidate for dependency-injection:
interface ITransportation {
decimal CalcCosts(double distance);
}
class Bus : ITransportation {
decimal CalcCosts(double distance) { return (decimal)(distance * 2); }
}
class Bicycle : ITransportation {
decimal CalcCosts(double distance) { return (decimal)(distance * 1); }
}
class Car: ITransportation {
decimal CalcCosts(double distance) { return (decimal)(distance * 3); }
}
Now you can easily create a new class Plane:
class Plane : ITransportation {
decimal CalcCosts(double distance) { return (decimal)(distance * 4); }
}
Now create a constrcutor for your calculator that expects an instance of ITransportation. Within your CostOfTravel-method you can now call ITransportation.CalcCosts(DistanceToDestination).
var calculator = new TransportationCostCalculator(new Plane());
This has the advantage that you can exchange your actual transportation-instance without any code-change to your TransportationCostCalculator-class.
To complete this design you might also create a TransportationFactory as follows:
class TransportationFactory {
ITransportation Create(string type) {
switch case "Bus": return new Bus(); break
// ...
}
Which you call like
ITransportation t = myFactory.Create("Bus");
TransportationCostCalculator calculator = new TransportationCostCalculator(t);
var result = myCalculator.CostOfTravel(50);
You could define an abstract class like this, and have each TransportationMethod extend the abstract class:
abstract class TransportationMethod {
public TransportationMethod() {
// constructor logic
}
abstract public double travelCost(double distance);
}
class Bicycle : TransportationMethod {
public Bicycle() : base() { }
override public double travelCost(double distance) {
return distance * 1;
}
}
class Bus : TransportationMethod {
public Bus() : base() { }
override public double travelCost(double distance) {
return distance * 2;
}
}
class Car : TransportationMethod {
public Car() : base() { }
override public double travelCost(double distance) {
return distance * 3;
}
}
So in your actual method call, it could be rewritten like this:
public decimal CostOfTravel(TransportationMethod t) {
return t.travelCost(DistanceToDestination);
}
You could use a strategy class for each type of travel. But, then you'd probably need a factory to create the strategy based upon the transport method which would likely have a switch statement to return the appropriate calculator.
public class CalculatorFactory {
public static ICalculator CreateCalculator(string transportType) {
switch (transportType) {
case "car":
return new CarCalculator();
...
public class CarCalculator : ICalculator {
public decimal Calc(double distance) {
return distance * 1;
}
}
....
You can make a Dictionary that returns a multiplier based on transport.
public class TransportationCostCalculator
{
Dictionary<string, int> multiplierDictionary;
TransportationCostCalculator ()
{
var multiplierDictionary= new Dictionary<string, int> ();
dictionary.Add ("Bicycle", 1);
dictionary.Add ("Bus", 2);
....
}
public decimal CostOfTravel(string transportMethod)
{
return (decimal) (multiplierDictionary[transportMethod] * DistanceToDestination);
}
I think the answer is some kind of database.
If you use some, the TransportCostCalculator ask the database for the multiplayer to the given transportmethod.
The database may be a text-file or an xml or an SQL-server. Simply a key-value-pair.
If you want to use code-only there is - tmo - no way to avoid the translation from transportmethod to multiplayer (or cost). So some kind of swicht is needed.
With the database you put the dictionary out of your code and you must not change your code to apply new transportmethods or change the values.
This is a case for the strategy design pattern. Create a base class, say TravelCostCalculator, then develop classes for each mode of travel you will consider, each overriding a common method, Calculate(double). You can then instantiate the specific TravelCostCalculator as needed using the factory pattern.
The trick is in how to construct the factory (without a switch statement). The way I do this is by having a static class constructor (public static Classname() - not an instance constructor) that registers each strategy class with the factory in a Dictionary<string, Type>.
Since C# does not run class constructors deterministically (like C++ does in most cases) you have to explicitly run them to ensure they will run. This could be done in the main program or in the factory constructor. The downside is that if you add a strategy class, you must also add it to the list of constructors to be run. You can either create a static method that must be run (Touch or Register) or you can also use System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor.
class Derived : Base
{
public static Derived()
{
Factory.Register(typeof(Derived));
}
}
// this could also be done with generics rather than Type class
class Factory
{
public static Register(Type t)
{
RegisteredTypes[t.Name] = t;
}
protected Dictionary<string, Type t> RegisteredTypes;
public static Base Instantiate(string typeName)
{
if (!RegisteredTypes.ContainsKey(typeName))
return null;
return (Base) Activator.CreateInstance(RegisteredTypes[typeName]);
}
}
I prefer to use Enum for that like this:
public enum TransportMethod
{
Bicycle = 1,
Bus = 2,
Car = 3
}
And use it like this method:
public decimal CostOfTravel(string transportMethod)
{
var tmValue = (int)Enum.Parse(typeof(TransportMethod), transportMethod);
return DistanceToDestination * tmValue;
}
Note that above method is case-sensitive, So you can capitalize first char;
Related Answer
It was said before but i want to give related topic another shot.
This is a good example for reflection.
"Reflection objects are used for obtaining type information at runtime. The classes that give access to the metadata of a running program are in the System.Reflection namespace."
By using reflection, you will avoid compiling code if another switch type such as train is wanted to add the program. You will solve the problem on the fly by using a config file.
I recently solved a similar problem with strategy patttern, by using dependency injection but I still end up with switch statement. It doesnt solve your problem this way. Method suggested by tyson still needs recompile if a new type added to dictionary.
An example of what i am talking about:
Dynamic Loading of Custom Configuration XML using Reflection in C# :
http://technico.qnownow.com/dynamic-loading-of-custom-configuration-xml-using-reflection-in-c/
Define a look up table array 3 by 2.
Look up rate value in array cell adjacent to transport type.
Calculate cost based on rate.
I'm thinking what is the best way to compare values from two different enums.
Example:
public enum ExampleEnumA
{
ExampleValue
}
public enum ExampleEnumB
{
ExampleValue
}
if (ExampleEnumA.ExampleValue.ToString() == ExampleEnumB.ExampleValue.ToString())
{
}
Comparing strings work, but I know that it's not the most efficient and eligent way. How it can be done better?
EDIT:
Maybe it's a design flaw, but it's problem from a real project, not my incorrect understanding of enums. This is how it looks like and there was no time to refactor whole approach.
public interface IProvider
{
Enum SectionType { get; }
}
public class FirstProvider : IProvider
{
public Enum SectionType
{
get { return ExampleEnumA.ExampleValue; }
}
}
public class SecondProvider : IProvider
{
public Enum SectionType
{
get { return ExampleEnumB.ExampleValue; }
}
}
public class Program
{
public void TmpMethod(Enum sectionType)
{
var provider = GetFromIoC...
if (provider.SectionType == sectionType)
{
//...
}
}
}
Enumerations are like an abstraction layer on top a regular class of integer-based constants.
That abstraction includes evaluating false even if two enumeraiton values are the same integer but belong to different enumeration types.
What's the best way of comparing two different enumeration types with same underlying value? I would answer that it should be a design flaw if you need to perform this evaluation.
For example, let's say we've implemented these enumerations:
public enum States
{
Open = 1,
Closed
}
public enum SpecialFolders
{
ProgramFiles86 = 1,
ProgramFiles64
}
Would make sense something like States.Open == SpecialFolders.ProgramFiles86? Potentially, they seem to be equal (they won't) because both enumeration values have an underlying value of 1, but 1 doesn't mean the same if the enumeration type isn't the same.
It's like saying that...
Bread
Meat
...is the same as:
Steal (Bread == Steal????????????)
Wood
Maybe...
...you can defeat the purpose of typing constants as enumerations casting them to int:
if ((int)ExampleEnumA.ExampleValue == (int)ExampleEnumB.ExampleValue)
{
}
...if the underlying type is int. It could also be long:
public enum SomeEnum : long
{
}
...and you would need to cast left and right part of your evaluation to long, and so on.
Anyway, I insist that you shouldn0t go this way. Maybe you should use a regular class of constants instead and you'll avoid 2 casts per evaluation:
public static class States
{
public const int Open = 1;
public const int Closed = 2;
}
public static class Materials
{
public const int Steel = 1;
public const int Wood = 1;
}
// true! but not that true... I can't understand why these constants equal...
if(States.Open == Materials.Wood)
{
}
BTW, I still consider this a design flaw and you should avoid not using enumerations to workaround a bad design decision.
I have an object that has properties of another object and one called DataValue, but the type that I want DataValue to return depends on information contained in the object in the other property. I'm not convinced my way is the best way to do this.
I have this business object called an AssetStructure.
An AssetStructure object contains a generic list of IAssetStructureField objects, which are a series of objects that basically hold information about the data that can be held in that field, a default value of a certain datatype and some displaying information properties. Each of the objects implementing the IAssetStructureField interface will hold different datatype. For example, one's DefaultValue's type maybe string and the other maybe a List<ofCustomType>.
I have my Asset object containing a generic list of objects called AssetDataField. The AssetDataField has properties of one containing the AssetStructureField and one called DataValue, the Asset's data for that StructureField.
My problem is datatype of AssetDataField DataValue property, it will need to be different depending on the details of the AssetStructureField object. This StructureField may hold data representing all the user groups with access to the Asset (datatype List<UserGroups>), and another might just be a description field (datatype string), so I need the DataValue coming out of the AssetDataField to be of the same type.
What I'm thinking of doing now, and that I feel can probably be done much better, is having the AssetDataField.DataValue return an object, and then cast it to the typeof the AssetDataField.StructureField.DefaultValue.
object fieldValue;
object fieldDefaultValue;
Asset certainAsset = new Asset(32423);
foreach (AssetDataField dataField in certainAsset.DataFields)
{
fieldDefaultValue = datafield.StructureField.DefaultValue;
fieldValue = datafield.DataValue as typeof(fieldDefaultValue);
// then do stuff depending on what typeof(fieldValue) is. This is where I
// see things getting particularly ugly. Not only just because that
// this class here will need to know the possible types that may be
// returned, so it can deal.
if (typeof(fieldValue) == whatever)
{
// deal;
}
else if (typeof(fieldValue) == whatever2)
{
// deal differently;
}
}
Does anyone have any suggestions? I am not a opposed, at all, to a complete redo. I'm really sorry this is so long-winded, I just wanted to try and explain the situation well. I tried to put together a UML diagram to help out, but my ArgoUML was acting up. Thanks for any insights at all that you can provide.
It seems like you should make AssetDataField a possibly abstract base class, and derive other classes from it to perform the work. For example:
class Program
{
static void Main(string[] args)
{
Asset certainAsset = new Asset(32423);
foreach (AssetDataField dataField in certainAsset.DataFields)
{
dataField.Deal();
}
}
}
class Asset
{
public List<AssetDataField> DataFields = new List<AssetDataField>();
public Asset(int id)
{
// Load asset #id
if (id == 32423)
{
DataFields.Add(new AssetDataFieldString());
DataFields.Add(new AssetDataFieldFloat());
}
}
}
abstract class AssetDataField
{
public AssetDataField()
{
FieldValue = DefaultValue;
}
public abstract object DefaultValue { get; }
public abstract object FieldValue { get; set; }
public abstract void Deal();
}
abstract class AssetDataFieldType<T> : AssetDataField
{
protected T internalValue;
public override object FieldValue
{
get
{
return TypedValue;
}
set
{
TypedValue = (T)System.Convert.ChangeType(value, typeof(T));
}
}
public virtual T TypedValue
{
get
{
return internalValue;
}
set
{
internalValue = value;
}
}
}
class AssetDataFieldString : AssetDataFieldType<string>
{
public override object DefaultValue
{
get { return "Default String"; }
}
// Optionally override TypedValue
public override void Deal()
{
Console.WriteLine(TypedValue.PadLeft(20));
}
}
class AssetDataFieldFloat : AssetDataFieldType<float>
{
public override object DefaultValue
{
get { return 0; }
}
// Optionally override TypedValue
public override void Deal()
{
Console.WriteLine(TypedValue.ToString("#0.000"));
}
}
Note: this smells like the result of querying an EAV based system. In the same way that meta data is the backbone of this sort of system the code referencing it should strive to know what it is accessing (and thus the types) at compile time. That said if you want to simply display the data this sort of thing is required no matter what.
C# is statically typed so you cannot put 'different things' into the same 'slot' (variable, array location) unless the slot is the right 'shape' to take all of them(1). The only slot currently available in c# for this is object. This will work but will box any value types(2).
In c# 4.0 you can use dynamic, which under the hood will be an object but at least will let you invoke any methods on it you want even if the compiler doesn't think it's legal via object.
If all the types in question share a common interface then you can avoid object and get some useful semantics (say if double Sum(double d) was a meaningful operation for any instance you were dealing with then this could yield useful results. However it sounds like you do not control the types present (and thus stand no chance of getting them to conform to useful interfaces).
If the set of possible types is tractable the technique described below can work but it is still cumbersome.
// boxes if needed
public interface IGeneralValue
{
object Value { get; }
Type GetValueType();
}
public class Value<T> : IGeneralValue
{
public T Value { get; set;}
object IGeneralValue.Value
{
get { return (object)this.Value; }
}
public Type GetValueType()
{
return typeof(T);
}
}
Then you can stay statically typed where possible but if not something similar to your previous code will work.
Asset certainAsset = new Asset(32423);
foreach (IGeneralValue dataField in certainAsset.DataFields)
{
object fieldValue = datafield.Value;
Type fieldType = dataField.GetValueType();
if (typeof(double).Equals(fieldType))
{
double d = ((double)fieldValue);
}
else if (typeof(string).Equals(fieldType))
{
string d = ((string)fieldValue);
}
else if (typeof(whatever).Equals(fieldType))
{
// deal with whatever
}
else
{
// the safe option
throw new NotSupportedException(fieldType +" is not supported!");
}
}
Without unsafe code or unions (only structs) at least.
This has implications not just on performance, you cannot unbox an int as a double for example, despite that conversion working on unboxed instances.
As a result of another question I asked here I want to use a HashSet for my objects
I will create objects containing a string and a reference to its owner.
public class Synonym
{
private string name;
private Stock owner;
public Stock(string NameSynonym, Stock stock)
{
name=NameSynonym;
owner=stock
}
// [+ 'get' for 'name' and 'owner']
}
I understand I need a comparer , but never used it before. Should I create a separate class? like:
public class SynonymComparer : IComparer<Synonym>
{
public int Compare(Synonym One, Synonym Two)
{ // Should I test if 'One == null' or 'Two == null' ????
return String.Compare(One.Name, Two.Name, true); // Caseinsesitive
}
}
I prefer to have a function (or nested class [maybe a singleton?] if required) being PART of class Synonym instead of another (independent) class. Is this possible?
About usage:
As i never used this kind of thing before I suppose I must write a Find(string NameSynonym) function inside class Synonym, but how should I do that?
public class SynonymManager
{
private HashSet<SynonymComparer<Synonym>> ListOfSynonyms;
public SynonymManager()
{
ListOfSymnonyms = new HashSet<SynonymComparer<Synonym>>();
}
public void SomeFunction()
{ // Just a function to add 2 sysnonyms to 1 stock
Stock stock = GetStock("General Motors");
Synonym otherName = new Synonym("GM", stock);
ListOfSynonyms.Add(otherName);
Synonym otherName = new Synonym("Gen. Motors", stock);
ListOfSynonyms.Add(otherName);
}
public Synonym Find(string NameSynomym)
{
return ListOfSynonyms.??????(NameSynonym);
}
}
In the code above I don't know how to implement the 'Find' method. How should i do that?
Any help will be appreciated
(PS If my ideas about how it should be implemented are completely wrong let me know and tell me how to implement)
A HashSet doesn't need a IComparer<T> - it needs an IEqualityComparer<T>, such as
public class SynonymComparer : IEqualityComparer<Synonym>
{
public bool Equals(Synonym one, Synonym two)
{
// Adjust according to requirements.
return StringComparer.InvariantCultureIgnoreCase
.Equals(one.Name, two.Name);
}
public int GetHashCode(Synonym item)
{
return StringComparer.InvariantCultureIgnoreCase
.GetHashCode(item.Name);
}
}
However, your current code only compiles because you're creating a set of comparers rather than a set of synonyms.
Furthermore, I don't think you really want a set at all. It seems to me that you want a dictionary or a lookup so that you can find the synonyms for a given name:
public class SynonymManager
{
private readonly IDictionary<string, Synonym> synonyms = new
Dictionary<string, Synonym>();
private void Add(Synonym synonym)
{
// This will overwrite any existing synonym with the same name.
synonyms[synonym.Name] = synonym;
}
public void SomeFunction()
{
// Just a function to add 2 synonyms to 1 stock.
Stock stock = GetStock("General Motors");
Synonym otherName = new Synonym("GM", stock);
Add(otherName);
ListOfSynonyms.Add(otherName);
otherName = new Synonym("Gen. Motors", stock);
Add(otherName);
}
public Synonym Find(string nameSynonym)
{
// This will throw an exception if you don't have
// a synonym of the right name. Do you want that?
return synonyms[nameSynonym];
}
}
Note that there are some questions in the code above, about how you want it to behave in various cases. You need to work out exactly what you want it to do.
EDIT: If you want to be able to store multiple stocks for a single synonym, you effectively want a Lookup<string, Stock> - but that's immutable. You're probably best storing a Dictionary<string, List<Stock>>; a list of stocks for each string.
In terms of not throwing an error from Find, you should look at Dictionary.TryGetValue which doesn't throw an exception if the key isn't found (and also returns whether or not the key was found); the mapped value is "returned" in an out parameter.
Wouldn't it be more reasonable to scrap the Synonym class entirely and have list of synonyms to be a Dictonary (or, if there is such a thing, HashDictionary) of strings?
(I'm not very familiar with C# types, but I hope this conveys general idea)
The answer I recommend (edited, now respects the case):
IDictionary<string, Stock>> ListOfSynonyms = new Dictionary<string,Stock>>();
IDictionary<string, string>> ListOfSynForms = new Dictionary<string,string>>();
class Stock
{
...
Stock addSynonym(String syn)
{
ListOfSynForms[syn.ToUpper()] = syn;
return ListOfSynonyms[syn.ToUpper()] = this;
}
Array findSynonyms()
{
return ListOfSynonyms.findKeysFromValue(this).map(x => ListOfSynForms[x]);
}
}
...
GetStock("General Motors").addSynonym('GM').addSynonym('Gen. Motors');
...
try
{
... ListOfSynonyms[synonym].name ...
}
catch (OutOfBounds e)
{
...
}
...
// output everything that is synonymous to GM. This is mix of C# and Python
... GetStock('General Motors').findSynonyms()
// test if there is a synonym
if (input in ListOfSynonyms)
{
...
}
You can always use LINQ to do the lookup:
public Synonym Find(string NameSynomym)
{
return ListOfSynonyms.SingleOrDefault(x => x.Name == NameSynomym);
}
But, have you considered using a Dictionary instead, I believe it is better suited for extracting single members, and you can still guarantee that there are no duplicates based on the key you choose.
I am not sure that lookup time is of SingleOrDefault, but I am pretty sure it is linear (O(n)), so if lookup time is important to you, a Dictionary will provide you with O(1) lookup time.