I'm building a translator that saves the translation in a dictionary where the first string is an identifier and the seconds string is the translated string.
It seems to me that the dictionary syntax is not very readable so I'm thinking about wrapping my dictionary like
class Translation : Dictionary<string,string>{}
and then also the keyvaluepair like
class SingleTranslation : KeyValuePair<string,string>
But the KeyValuePair class is sealed (can not be inherited). Does anyone have any suggestions on how I can make my dictionary more readable?
My biggest worry is when I have to iterate over the dictionary with
foreach(KeyValuePair<string,string> kvp in _translation)
{
string whatever = kvp.Value;
do stuff...
if(kvp.key)
do stuff..
}
I could of course create a string in the foreach that is called Identifier and set it equal to kvp.key. But I would prefer something like
foreach(SingleTranslation singleTranslation in _translation)
{
singleTranslation.Identifier ... do stuff...
}
Don't do that. Either use Dictionnary directly for complete access or use composition if you want more control.
Also use var in foreach loops. There is no value in defining a custom type for that (and it should not even works as you try to convert KeyValuePair to a derived class. And by the way, this is one reason why it is sealed.
If you really want to use custom types, and do not want to write much custom code, then maybe something like that could works for you:
class Translation
{
public Dictionary<string,string> Data { get } = new Dictionary<string,string>;
}
Then you could do:
Translation t; // Fill some data...
foreach (var item in t.Data) { … }
That way, you can ensure that you don't pass the improper dictionary to functions as you use distinct types for each case:
void DisplayTranslation(Translation t) { … }
If you want, you could improve your Translation class so that it does not expose the internal dictionary but expose appropriate members, properties and interfaces for the desired usage.
You could always use something other than a dictionary, like a class that inherits from List and then add an indexer on it so you could still use syntax like translations["myIndex"]. The code below could be optimized, but you can get the idea.
public class Translations : List<SingleTranslation>
{
public SingleTranslation this[string identifier]
{
get
{
return this.FirstOrDefault(p => p.Identifier == identifier);
}
set
{
SingleTranslation translation = this.FirstOrDefault(p => p.Identifier == identifier);
if (translation == null)
{
this.Add(value);
}
else
{
translation.Value = value.Value;
}
}
}
}
public class SingleTranslation
{
public SingleTranslation(string identifier, string value)
{
Identifier = identifier;
Value = value;
}
public string Identifier { get; set; }
public string Value { get; set; }
}
Sample usage:
public class Program
{
public static void Main()
{
Translations translations = new Translations();
translations.Add(new SingleTranslation("hello", "hola"));
translations.Add(new SingleTranslation("day", "día"));
foreach(SingleTranslation translation in translations)
{
Console.WriteLine("{0}: {1}", translation.Identifier, translation.Value);
}
translations["hello"].Value = "salut";
translations["day"].Value = "jour";
foreach(SingleTranslation translation in translations)
{
Console.WriteLine("{0}: {1}", translation.Identifier, translation.Value);
}
}
}
A working example of this is in this fiddle:
If readability is simply your issue, you could alias it within the namespace declaration.
using SingleTranslation = KeyValuePair<string,string>;
Related
Recently, when handling collections of objects of the same (base-)class,
I´ve recently found myself writing something like this:
class SomeClass {
public bool PropertyA {get; set;}
}
class EncapsulatingClass {
private List<SomeClass> list = new();
private bool propA;
public bool PropertyA {
get { return propA; }
set {
propA = value;
foreach(SomeClass instance in list)
instance.PropertyA = value;
}
}
}
This is of course so I don´t have to use foreach every time I want to set a property for the collection. While this works fine, I feel like this requires a lot of code for something simple and a lot of repitition with each property.
Is there a better solution, like extracting the logic of "apply this for the property of the same name for each object in the list" into a function and just calling that in the setters?
There is the issue of ownership of the property. If you need to enforce synchronization such that setting PropertyA ins the encapsulating class, all the instances in the list also use the same value.
For example
class SomeClass
{
public SomeClass(EncapsulatingClass parent)
{
Parent=parent;
}
public EncapsulatingClass Parent { get; }
public bool PropertyA { get => Parent.PropertyA; }
}
class EncapsulatingClass
{
private List<SomeClass> list = new List<SomeClass>();
private bool propA;
public bool PropertyA
{
get { return propA; }
set
{
propA = value;
}
}
}
Otherwise, you have multiple PropertyA values, one for each instance, and then you have to decide which one is the master value, and what to do if some are different.
I'm wondering what it is you are doing to need this so often. It makes me think there's a flaw in the design of your application you could avoid by restructuring something but it's difficult to say without more information.
For your specific problem I would discard EncapsulatingClass and use the ForEach method on List<T> for a little more concise code:
myList.ForEach(s => s.PropertyA = true);
Alternatively, if you don't always use List<T> you can write your own extension method to work on all IEnumerables:
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
foreach (var t in source)
action(t);
}
// Call it just like previously:
myIEnumerable.ForEach(s => s.PropertyA = true);
Of course, this is still cumbersome if you need to do it a lot. But I suspect if you do, it's probably a flaw in the design.
I might approach this with a custom List class providing a single mass update method.
public class EasyUpdateList<T> : List<T>
{
public void UpdateAll(Action<T> update)
{
if (update == null)
return;
foreach (T item in this)
update(item);
}
}
Now you don't need a specific encapsulating class, you can just create a new EasyUpdateList and update any number of properties across the collection using the UpdateAll method.
EasyUpdateList<MyClass> list = new EasyUpdateList<MyClass>();
list.Add(instance1);
list.Add(instance2);
...
list.UpdateAll(x =>
{
x.Property1 = "Value1";
x.Property2 = "Value2";
});
This still uses a foreach loop but is much more generic and you don't have to change your other classes or write repeated code for each one.
Of course you could also achieve this with an extension method for a List class if you don't want a new class.
public static void UpdateAll<T>(this IList<T> list, Action<T> update)
{
if (update == null)
return;
foreach (T item in list)
update(item);
}
I'm trying to find a way to refine some code that I have. I work with a 3rd party API that has a REALLY complicated API request object (I'll call it ScrewyAPIObject) that has tons of repetition in it. Every time you want to set a particular property, it can take a page worth of code. So I built a library to provide a simplified wrapper around the setting/getting of its properties (and to handle some value preprocessing).
Here's a stripped-down view of how it works:
public abstract class LessScrewyWrapper
{
protected ScrewyAPIRequest _screwy = new ScrewyAPIRequest();
public void Set(string value)
{
Set(_getPropertyName(), value);
}
public void Set(string property, string value)
{
// Preprocess value and set the appropriate property on _screwy. This part
// has tons of code, but we'll just say it looks like this:
_screwy.Fields[property] = "[" + value + "]";
}
protected string _getPropertyName()
{
// This method looks at the Environment.StackTrace, finds the correct set_ or
// get_ method call and extracts the property name and returns it.
}
public string Get()
{
// Get the property name being access
string property = _getPropertyName();
// Search _screwy's structure for the value and return it. Again, tons of code,
// so let's just say it looks like this:
return _screwy.Fields[property];
}
public ScrewyAPIRequest GetRequest()
{
return _screwy;
}
}
Then I have a child class that represents one specific type of the screwy API request (there are multiple kinds that all have the same structure but different setups). Let's just say this one has two string properties, PropertyA and PropertyB:
public class SpecificScrewyAPIRequest : LessScrewyWrapper
{
public string PropertyA
{
get { return Get(); }
set { Set(value); }
}
public string PropertyB
{
get { return Get(); }
set { Set(value); }
}
}
Now when I want to go use this library, I can just do:
SpecificScrewyAPIRequest foo = new SpecificScrewyAPIRequest();
foo.PropertyA = "Hello";
foo.PropertyB = "World";
ScrewyAPIRequest request = foo.GetRequest();
This works fine and dandy, but there are different kinds of data types, which involves using generics in my Set/Get methods, and it just makes the child classes look a little kludgy when you're dealing with 50 properties and 50 copies of Get() and Set() calls.
What I'd LIKE to do is simply define fields, like this:
public class SpecificScrewyAPIRequest : LessScrewyWrapper
{
public string PropertyA;
public string PropertyB;
}
It would make the classes look a LOT cleaner. The problem is that I don't know of a way to have .NET make a callback to my custom handlers whenever the values of the fields are accessed and modified.
I've seen someone do something like this in PHP using the __set and __get magic methods (albeit in a way they were not intended to be used), but I haven't found anything similar in C#. Any ideas?
EDIT: I've considered using an indexed approach to my class with an object-type value that is cast to its appropriate type afterwards, but I'd prefer to retain the approach where the property is defined with a specific type.
Maybe in your case DynamicObject is a suitable choice:
public class ScrewyDynamicWrapper : DynamicObject
{
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
// get your actual value based on the property name
Console.WriteLine("Get Property: {0}", binder.Name);
result = null;
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
// set your actual value based on the property name
Console.WriteLine("Set Property: {0} # Value: {2}", binder.Name, value);
return true;
}
}
And define your wrapper objects:
public class ScrewyWrapper
{
protected dynamic ActualWrapper = new ScrewyDynamicWrapper();
public int? PropertyA
{
get { return ActualWrapper.PropertyA; }
set { ActualWrapper.PropertyA = value; }
}
public string PropertyB
{
get { return ActualWrapper.PropertyB; }
set { ActualWrapper.PropertyB = value; }
}
}
However, you can't rely on the property type inside ScrewyDynamicWrapper with this approach, so it depends on your actual API requirements - maybe it won't work for you.
Instead of fields, If you define as property in class, It will be more easy.
public class SpecificScrewyAPIRequest
{
public string PropertyA { get; set; }
public string PropertyB { get; set; }
}
Then you can create extension generic method to return ScrewyAPIRequest object.
public static class Extensions
{
public static ScrewyAPIRequest GetRequest<T>(this T obj)
{
ScrewyAPIRequest _screwy = new ScrewyAPIRequest();
var test= obj.GetType().GetProperties();
foreach (var prop in obj.GetType().GetProperties())
{
_screwy.Fields[prop.Name] = prop.GetValue(obj, null);
}
return _screwy;
}
}
Now you can easily get ScrewyAPIRequest from any class object.
Your code will look like following.
SpecificScrewyAPIRequest foo = new SpecificScrewyAPIRequest();
foo.PropertyA = "Hello";
foo.PropertyB = "World";
ScrewyAPIRequest request = foo.GetRequest();
first off - yes, I had a look at this question: Is object creation in getters bad practice?.
I am also not talking about initializing an object in the accessors / mutators, it is about a specific part of the object I want to be returned in a specific way.
My question is more specific; It does not necessarily only apply to C#, however I am currently looking for a solution to implement in my C# project.
I have a class with a dictionary that maps date objects to a decimal value. In one accessor, I want to return a list of all the keys of the dictionary, another accessors returns the values.
What I also want to have is an accessor that gives me the decimal values in a specific format. It would look something like this:
class Class
{
// Some other properties...
// ....
private Dictionary<DateTime, decimal> dict;
public Class(Dictionary<DateTime, decimal> dict)
{
this.dict = dict;
}
private string FormatTheWayIWant(decimal dt)
{
// Format decimal value.
string s = String.Format("{0:F}", dt);
return s;
}
public ReadOnlyCollection<DateTime> DateTimes
{
get { return new ReadOnlyCollection<DateTime>(this.dict.Keys.ToList()); }
}
public ReadOnlyCollection<decimal> Values
{
get { return new ReadOnlyCollection<decimal>(this.dict.Values.ToList()); }
}
public ReadOnlyCollection<string> FormattedStrings
{
get
{
// Format each decimal value they way I want.
List<string> list = new List<string>();
foreach (decimal dt in dict.Keys)
{
list.Add(FormatTheWayIWant(dt));
}
return new ReadOnlyCollection<string>(list);
}
}
}
This way I can make the following calls (which is my goal!):
DateTime dateTime = DateTimes[0];
decimal s = Values[0];
string formattedS = FormattedStrings[0];
The problem with this approach is that I create a new list everytime I invoke the FormattedStrings accessor, even if I only need one of the formatted strings. I know this is not good practice and can introduce unnecessary performance issues...
The alternatives I thought of are:
I could extend the decimal class and implement a custom ToString()-method.
Or overwrite the KeyValuePair<DateTime, decimal> class and use an indexer in my class.
Or I create a method with a parameter for the index and return just the one formatted string.
Or I could have an own list for the accessor, which gets updated in the set-method for my dictionary everytime I update the dictionary.
The question I have is, is there a way to make this work with an accessor instead of a method, creating custom classes or having strange side effects on other objects when assigning a value?
Thank you in advance.
Ofcourse this can be done with an accessor. You just have to create 3 separate classes for each desired element of your processed collection. Those classes should have their own indexers, so you would be able to access the elements as a list. The difference would be, that they compute each element on demand (wchich is called lazy initialization). So it would go like this (example for your FormattedStrings):
class Class
{
// ...
MyFormattedStrings FormattedStrings
{
get {return new MyFormattedStringsIndexer<string>(this.dict.Values.ToList());}
}
}
class MyFormattedStringsIndexer<T>
{
private IList<T> list; // we take only reference, so there is no overhead
public MyFormattedStringsCollection (IList<T> list)
{
this.list = list;
}
// the indexer:
public T this[int i]
{
get
{
// this is where the lazy stuff happens:
// compute the desired element end return it
}
set
{
// ...
}
}
}
Now you can use your Class like this:
string formattedS = FormattedStrings[5];
and each element you access will be computed as you access it. This solution also has the advantage of separating concerns, so should you ever had to implement different logic for one of your 3 accessors it would be just a matter of extending one of the indexers.
You can read more about indexeres here: http://msdn.microsoft.com/en-us/library/6x16t2tx.aspx
This is VB, but you get the idea...
Public Class Something
Public Property Items As Dictionary(Of DateTime, String)
Public Readonly Property FormattedItem(ByVal index As Int32) As String
' add error checking/handling as appropriate
Return Me.Items.Keys(index).ToString("custom format") ' or whatever your formatting function looks like.
End Property
End Class
It looks like a good candidate for a new class
public class MyObject
{
public DateTime Key {get;set;}
public String Name {get;set;}
public String FormattedString {get;}
}
And then it can be used in any container (List<MyObject>, Dictionary<MyObject>, etc).
Your Dates and Strings property getters are returning a new list on each call. Therefore if a caller does the following:
Class myClass = ...
for(i=0; i<myClass.Strings.Count; i++)
{
var s = myClass.Strings[i];
...
}
then each iteration of the loop will create a new list.
I'm not clear on what you're really trying to achieve here. You are wrapping the dictionary's Keys and Values properties in ReadOnlyCollections. This gives you an indexer, which doesn't have much meaning as the order of the Keys in a Dictionary<TKey, TValue> is unspecified.
Coming (at last!) to your question, if you want to do the formatting in a "lazy" manner, you could create a custom class that implements a readonly IList<string>, and wraps your list of keys (IList<DateTime>). Most of the implementation is boilerplate, and your indexer will do the formatting. You could also cache the formatted values so that you only format once if accessed multiple times. Something like:
public class MyFormattingCollection : IList<string>
{
private IList<decimal> _values;
private IList<string> _formattedValues;
public MyFormattingCollection(IList<DateTime> values)
{
_values = values;
_formattedValues = new string[_values.Count];
}
public string this[int index]
{
get
{
var result = _formattedValues[index];
if (result == null)
{
result = FormatTheWayIWant(_values[index]);
_formattedValues[index] = result;
}
return result;
}
set
{
// Throw: it's a readonly collection
}
}
// Boilerplate implementation of readonly IList<string> ...
}
Ok, i have a class which is as follows:
public class MT101
{
// Sequence A
public string tag20 { get; set; } // 16x
public string tag21R { get; set; } // 16x
public string tag28D { get; set; } // 16x
public List<String> tag50; // Option F, G, H, C, or L
}
i then have a method, which make a new instance of said class as follows:
public class CheckMessage
{
private List<MT101> Message101 = new List<MT101>();
public List<MT101> CheckMt101Message(string[] messageBody)
{
MT101 buildMessage = new MT101();
.
.
. perform all the neccessary logic to add into buildMessage and then return the
. Message101 object
Message101.Add(buildMessage);
return Message101;
}
}
I call the Method from another class as such:
GlobalClasses.CheckMessage gm = new GlobalClasses.CheckMessage();
and pass in the variables as such:
string[] _block4 = Regex.Split(trimmed, #"\r\n");
gm.CheckMt101Message(_block4);
foreach (GlobalClasses.CheckMessage item in gm)
{ }
In visual studio, i get the following errors when compiled:
Error 1 GlobalClasses.MT101.System.Collections.IEnumerable.GetEnumerator()': containing type does not implement interface 'System.Collections.IEnumerable'
Error 2 foreach statement cannot operate on variables of type 'GlobalClasses.CheckMessage' because 'SASMI.GlobalClasses.CheckMessage' does not contain a public definition for 'GetEnumerator'
I've googled and found reference to setting IEnumerable to the class, so 'ive tried this:
public class Mt101 : IEnumberable
same message being reported.
I guess you want to iterate over the MT101 objects in the Message101 field in the class. The easiest way to accomplish this, is to make Message101 public, e.g.:
public class CheckMessage
{
private List<MT101> message101 = new List<MT101>();
public List<MT101> Messge101 { get { return message101; } }
public List<MT101> CheckMt101Message(string[] messageBody)
{
MT101 buildMessage = new MT101();
.
.
. perform all the neccessary logic to add into buildMessage and then return the
. Message101 object
Message101.Add(buildMessage);
return Message101;
}
}
And then you can iterate over these objects:
foreach (MT101 item in gm.Message101)
{
// ...
}
You are ignoring the return value of CheckMt101Message and instead try to iterate on the class itself. That won't work. Save the return value and iterate over it:
var messages = gm.CheckMt101Message(_block4);
foreach (Mt101 item in messages)
{
...
}
this is one of the procedures to iterate through the loop
EMP oeemp= new EMP();
List<EMP> tr= new List<EMP>();
foreach(var t in tr)
{
}
If you want to iterate on the internal List using the reference to the class CheckMessage then you need to implement a function that returns an IEnumerator like this
in CheckMessage class
public IEnumerator<MT101> GetEnumerator()
{
foreach (MT101 m in this.Message101)
{
yield return m;
}
}
in your code
foreach(MT101 m in gm)
{
.....
}
Of course you could execute the foreach also on the return value of CheckMt101Message but the yield keyword allows a couple of advantages. You need to have just the reference to the CheckMessage class, you don't need to make your internal list public, you could execute the loop at any moment using only the CheckMessage reference and you could add custom code before and after the yeld.
You have to do
foreach (MT101 item in gm.CheckMt101Message(_block4)) { ... }
I'm afraid you have a big confusion so I recommend you to check yourself about why your code is not working, this would be much more helpful for you than just copy paste any of provided solutions.
I have class called GroupItem, i can store any type here say int, string, decimal, datetime etc.., Then, i have GroupItems which will store any groupItem. I'm using an arraylist to store all the groupItem.
public class GroupItem<T>
{
private string heading;
private List<T> items = new List<T>();
public GroupItem() { }
public string Heading
{
get { return heading; }
set { heading = value; }
}
public List<T> Items
{
get { return items; }
set { items = value; }
}
public void Add(T value)
{
this.items.Add(value);
}
public T this[int index]
{
get
{
return this.items[index];
}
}
}
public class GroupItems
{
private string groupName;
private List<object> items = new List<object>();
public string GroupName
{
get { return groupName; }
set { groupName = value; }
}
public GroupItems() { }
public void Add(object value)
{
this.items.Add(value);
}
public object this[int index]
{
get
{
return this.items[index];
}
}
}
I want to retrieve from GroupItems. How i can get generic item's values in groupItems?
I'm now inserting two items, datetime and int to groupitems. Now i want to retrieve groupitems[2] value but how i can convert this to groupItem without knowing what it is. Even we may get its genericarguments by getType().getGenericarguments()[0]. But how i can create an instance based upon that.
If the list is storing heterogeneous items, then I would suggest you need a common non-generic interface or base-class. So, say we have
interface IGroupItem {
// the non-generic members, and maybe
// "object Value {get;}" etc, and maybe
// "Type ItemTypr {get;}"
}
You would then have:
class GroupItem<T> : IGroupItem {...}
an you would then use
List<IGroupItem> ...
instead of ArrayList, or, franky, in place of GroupItems {...}
What I'd do is create a generic collection such as:
public class GroupItems<T> : List<GroupItem<T>>
{
}
If you need to extend the basic functionality of a list, you could also extend Collection<T> and override the methods you need:
public class GroupItems<T> : Collection<GroupItem<T>>
{
protected override void InsertItem(int index, T item)
{
// your custom code here
// ...
// and the actual insertion
base.InsertItem(index, item);
}
}
How about just replacing your GroupItems class with List<GroupItem<T>> ?
Depending on what you do with GroupItem you should either inherit from List/Collection as was offered by other or use a generic collection inside your class
e.g.
class GroupItem<T>
{
private List<T> items = new List<T>();
public void Add(T value)
{
items.Add(value);
}
public T Get()
{
//replace with some logic to detemine what to get
return items.First();
}
}
There are two situations that could be covered by your question:
You want to simply store a collection of GroupItem's of type T in the class GroupItems.
You want to store a collection of generic GroupItem's of any type in the class GroupItems. To better clarify, I mean that you could store GroupItem<DateTime> or GroupItem<int> in the same GroupItems class.
Here are some ways of going about storing and retrieving for both scenarios:
Same Type
public class GroupItem<T>
{
// ... Code for GroupItem<T>
}
public class GroupItems<T>
{
private List<GroupItem<T>> mItems = new List<GroupItem<T>>();
public void Add(T item)
{
mItems.Add(item);
}
public T GetItem(int index)
{
return mItems[index];
}
}
Here you will build a collections that contain GroupItem's of the same time, so a collection of GroupItem<DateTime> for example. All the items will be of the same type.
Generic Type
public interface IGroupItem
{
// ... Common GroupItem properties and methods
}
public class GroupItem<T>
{
// ... Code for GroupItem<T>
}
public class GroupItems
{
private List<IGroupItem> mItems = new List<IGroupItem>();
public void Add(IGroupItem item)
{
mItems.Add(item);
}
// This is a generic method to retrieve just any group item.
public IGroupItem GetItem(int index)
{
return mItems[index];
}
// This is a method that will get a group item at the specified index
// and then cast it to the specific group item type container.
public GroupItem<T> GetItem<T>(int index)
{
return (GroupItem<T>)mItems[index];
}
}
Here you will be able to build and maintain a single collection that can contain any GroupItem with any Type. So you could have a GroupItems collection that contains items of GroupItem<DateTime>, GroupItem<int>, etc.
Please note that none of these code examples take into account any erroneous circumstances.
Consider: you have a collection of items; the items may have any runtime type (string, int, etc.). Because of this, the static type of the collections items must be object.
It seems that you want to be able to retrieve items from the list with strong static typing. That's not possible without a lot of conditional logic (or reflection). For example:
object item = collection[0];
if (item is int)
//do something with an int
else if (item is string)
//do something with a string
Now suppose instead of "doing something" with the value of collection[0], we assign the value to a variable. We can do one of two things:
use the same variable for both cases, in which case the static type must be object.
use separate variables, in which case the static type will be string or int, but outside of the conditional logic, we can't know which variable holds the value of collection[0].
Neither option really solves the problem.
By creating GroupItem<T>, you add a level of indirection to this problem, but the underlying problem is still there. As an exercise, try reworking the example, but starting from "Consider: you have a collection of items; the items are of type GroupItem<T> where T may be any runtime type (string, int, etc.)."
Thanks for your inputs.
I have resolved it myself using multiple overloading methods to resolve this.
for example:
private void Print(GroupItem<string> items)
{
///custom coding
}
private void Print(GroupItem<int> items)
{
///custom coding
}
Though its not efficient enough, i want to do in this way as it was .net 2.0.
I'm now improving this in .Net 4.0 with new algorithm.
Thanks a lot for all of your helps.