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.
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 use List.Contains to find if item in list, has it's bool true or false
Problem is, no matter if the bool is true or false, function always return's false.. her's an example
public class RecepieClass
{
public Recepie recepie;
public bool isUnlocked;
}
public class RecepieList : MonoBehaviour
{
public List<RecepieClass> recepies = new List<RecepieClass>();
public void SelectRecepie(Recepie r)
{
Debug.Log(recepies.Contains(new RecepieClass{recepie = r, isUnlocked = false}));
}
}
Use a for loop, and examine the recipe property of each RecipeClass item. If you know that the Recepie parameter being passed to the function is the actual instance of one of the RecepieClass items in your list, then the default Object.Equals method will work. If it is another instance, you'll need to define your own Equals method (i.e., Recepie should implement IEquatable).
public class RecepieClass
{
public Recepie recepie;
public bool isUnlocked;
}
public class RecepieList : MonoBehaviour
{
public List<RecepieClass> recepies = new List<RecepieClass>();
public void SelectRecepie(Recepie r)
{
foreach (var rc in recepies) {
if (rc.recepie.Equals(r)) {
// you've found it
if (rc.isUnlocked) {
// do something
} else {
// do something else
}
break;
}
}
}
}
If you're into the whole brevity thing, you could use System.Linq.FirstOrDefault (just be prepared for it to return a null).
public void SelectRecepie(Recepie r)
{
if (recepies.FirstOrDefault(rc => rc.recepie.Equals(r))?.isUnlocked ?? false) {
// do something
}
}
When comparing reference types the comparison is determining if objects point to the same object (assuming class doesn't override IEquatable). What you are tying to find is an item with the same values.
The safest way to find an item within a collection is to use a unique identifier within the item combined with the FirstOrDefault() method.
Given there is nothing that seems unique on RecepieClass the example below assumes there is an Id within Recepie referenced from RecepieClass.
var recipe = recepies.FirstOrDefault(r => r.recepie?.Id == 123456);
Debug.Log(recipe);
With the above example recipe will be null or the first RecepieClass with a Recepie matching the supplied id value (123456 in the example).
I dont know if your value r is unique in List or not. i just trap the first found
you just write: (with using System.Linq)
public void SelectRecepie(Recepie r)
{
var result = recepies.FirstOrDefault(x => x.recepie.Equals(r)).isUnlocked;
Debug.Log(result);
}
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>;
I have two List<> with the same field that I need to edit. How to write a common function for these lists?
public List<?> CutField(List<?> list)
{
foreach(var element in list)
{
element.Field = // ;
}
return List<?>;
}
Best way would be using generics:
public List<T> CutField<T>(List<T> list) where T : MyInterface
{
foreach(T element in list)
{
element.Field = // ;
}
return list;
}
With
public interface MyInterface
{
object Field { get; set; } // or whatever datatype you need for the field
}
Of course all the possible types within your list should implement that interface.
As an aside you can also omit the return-type from CutField, as you´re already modifying the list passed as parameter.
I want to copy values from one object to another object. Something similar to pass by value but with assignment.
For example:
PushPin newValPushPin = oldPushPin; //I want to break the reference here.
I was told to write a copy constructor for this. But this class has a lot of properties, it will probably take an hour to write a copy constructor by hand.
Is there a better way to assign an object to another object by value?
If not, is there a copy constructor generator?
Note: ICloneable is not available in Silverlight.
If you can mark the object that is to be cloned as Serializable then you can use in-memory serialization to create a copy. Check the following code, it has the advantage that it will work on other kinds of objects as well and that you don't have to change your copy constructor or copy code each time an property is added, removed or changed:
class Program
{
static void Main(string[] args)
{
var foo = new Foo(10, "test", new Bar("Detail 1"), new Bar("Detail 2"));
var clonedFoo = foo.Clone();
Console.WriteLine("Id {0} Bar count {1}", clonedFoo.Id, clonedFoo.Bars.Count());
}
}
public static class ClonerExtensions
{
public static TObject Clone<TObject>(this TObject toClone)
{
var formatter = new BinaryFormatter();
using (var memoryStream = new MemoryStream())
{
formatter.Serialize(memoryStream, toClone);
memoryStream.Position = 0;
return (TObject) formatter.Deserialize(memoryStream);
}
}
}
[Serializable]
public class Foo
{
public int Id { get; private set; }
public string Name { get; private set; }
public IEnumerable<Bar> Bars { get; private set; }
public Foo(int id, string name, params Bar[] bars)
{
Id = id;
Name = name;
Bars = bars;
}
}
[Serializable]
public class Bar
{
public string Detail { get; private set; }
public Bar(string detail)
{
Detail = detail;
}
}
There is a protected member called "MemberwiseClone", you can write this in your class...
public MyClass Clone(){
return (MyClass)this.MemberwiseClone();
}
then you can access..
MyClass newObject = oldObject.Clone();
The only way (that I'm aware of) to do this, and do it correctly, is to implement the copy yourself. Take for example:
public class FrobAndState
{
public Frob Frobber { get; set;}
public bool State { get; set; }
}
public class Frob
{
public List<int> Values { get; private set; }
public Frob(int[] values)
{
Values = new List<int>(values);
}
}
In this example you'd need to know how Frob was implemented, i.e. the fact that you need to call the constructor to create a copy of it as Values is read-only, to be able to make a copy of a given instance of FrobAndState.
Also - you couldn't just implement FrobAndState.Copy thusly:
public class FrobAndState
{
// ... Properties
public FrobAndState Copy()
{
var new = new FrobAndState();
new.State = this.State;
new.Frobber = this.Frobber;
}
}
Because both the instance of FrobAndState that you called .Copy() on, and the new instance would both have a reference to the same instance of Frobber.
In short, copying things is hard and any Copy implementation is difficult to get right.
C# does not have a copy constructor. There are different ways to tackle this. At the OOP level you could use inheritance or aggregation. AutoMapper might also be worth a try.
I want to copy values from one object
to another object. Something similiar
to pass by value but with assignment.
What do you mean by "with assignment"? If you mean that you want people to be able to say:
a = b;
And for you to define what = means, the only way you can do that in C# is if b is a different type to a and you've defined an implicit conversion (or more tenuously, if a stands for something of the form x.Y where Y is a property with a setter). You can't override = for a simple assignment between identical types in C#.
I was told to write a copy constructor
for this. But this class has alot of
properties, it will probably take an
hour to write a copy constructor by
hand.
If that's really true, then I would guess that you have a different problem. Your class is too big.
If you make your class Serializable you could Serialize it to a MemoryStream and Deserialize to a new instance.
If you want copy-on-assignment you should be using a struct instead of a class. But be careful, it is easy to make subtle mistakes. It is highly recommended that all stucts be immmutable to reduce the chance for error.
Though, this may not answer your question directly, but to add a cent; usually the term Clone is linked with shallow copy(referenced objects). To have a deep copy, I believe you will need to look into the some creational pattern(prototype?). The answer to this question might help.
You implement Justin Angel's method of cloning objects in Silverlight
using System;
using System.Reflection;
using System.Windows;
namespace JustinAngelNet.Silverlight.Framework
{
public static class SilverlightExtensions
{
public static T Clone<T>(T source)
{
T cloned = (T) Activator.CreateInstance(source.GetType());
foreach (PropertyInfo curPropInfo in source.GetType().GetProperties())
{
if (curPropInfo.GetGetMethod() != null
&& (curPropInfo.GetSetMethod() != null))
{
// Handle Non-indexer properties
if (curPropInfo.Name != "Item")
{
// get property from source
object getValue = curPropInfo.GetGetMethod().Invoke(source, new object[] {});
// clone if needed
if (getValue != null && getValue is DependencyObject)
getValue = Clone((DependencyObject) getValue);
// set property on cloned
if (getValue != null)
curPropInfo.GetSetMethod().Invoke(cloned, new object[] {getValue});
}
// handle indexer
else
{
// get count for indexer
int numberofItemInColleciton =
(int)
curPropInfo.ReflectedType.GetProperty("Count").GetGetMethod().Invoke(source, new object[] {});
// run on indexer
for (int i = 0; i < numberofItemInColleciton; i++)
{
// get item through Indexer
object getValue = curPropInfo.GetGetMethod().Invoke(source, new object[] {i});
// clone if needed
if (getValue != null && getValue is DependencyObject)
getValue = Clone((DependencyObject) getValue);
// add item to collection
curPropInfo.ReflectedType.GetMethod("Add").Invoke(cloned, new object[] {getValue});
}
}
}
}
return cloned;
}
}
}
Then you can do this
MyClass newObject = SilverlightExtensions.Clone(oldObject);