This is purely academic, but how would I create a method like the ForEach?
Say if I wanted to do something like the following:
SomeTenumerable.MyOwnFunction(x =>
{
x.Id = 0;
x.Order_Id = 0;
});
Note: I've only just got familiar with func<T,TResult>, so I'm not sure if it's the same thing.
Extra points if you can tell me the proper name/label of what I'm trying to achieve, I'm guessing it's some sort of delegate?
Demo here - https://dotnetfiddle.net/v7JKoo
.Each extension I use regularly - taken from http://extensionmethod.net/csharp/ienumerable-t/each-t
public static void Each<T>(this IEnumerable<T> items, Action<T> action)
{
if (items == null) return;
foreach (var item in items)
action(item);
}
Example:
var items = new List<Item>();
// populate items
items.Each(item => item.DoSomething());
Yes you are passing in a delegate (here it is an Action) to perform on each item
PS if you are looking to return items look at linqs .Where or .Select
I think what you want to do is create an extension method (MSDN)
ForEach is a method in the List class (you can see the code here). Since you cannot add a method to the class, you can create an extension method that lives in your project but can be used as it was part of the original List class.
Let's say your items use this interface
public interface IYourInterface
{
int Id;
int Order_Id;
}
You create a static method in a static class:
static class HelperMethods
{
public static void ResetAll(this List<IYourInterface> collection)
{
collection.ForEach(x =>
{
x.Id = 0;
x.Order_Id = 0;
});
}
}
And then use the method on any instance of List.
var collection = new List<IYourInterface>();
collection.ResetAll();
var otherStuff = new List<string>();
// This won't work because because List<string> cannot
// be converted to List<IYourInterface>
// otherStuff.ResetAll();
Add Property class
Public MyClass
{
public static int Id {get;set;}
public static int Order_Id{get;set;}
}
You can set it like this
IEnumerable<MyClass> myclass = new IEnumerable<MyClass>(
{
Id = 0;
Order_Id = 0;
});
You can query through, serach throw etc.
See this question, Here The question itself not the anwer.
Related
I need to return one row of List from my function Selectus.
So I pass to the function Selectus object that reflects database table fields and I need to return one row which match the parameter looking_for:
public static List<T> Selectus<T>(string looking_for)
{
//all select data
var db = OrmLiteBaza().Open();//opening database
var select_all_list = db.Select<T>();//getting all data for <T> object works fine
db.Dispose();
//try to select one row - here I have trouble:
var prop = typeof(T).GetProperties();//properties of passed <T> object
var list_selected_record = from records in select_all_list where prop[1].Name == looking_for select records;//tryin to select one record from <T> object as in looking_for variable
return list_selected_record.ToList();//here one record should be returned
}
I do not know how to select one row from the list assuming that T parameter is vary. In SelectusT> method I want to pass as T different objects which reflect fields in database table rather than creatinig separate methods for each select. e.g. call Selectus, where object passed is public class ProductCodes { public int ID { get; set; } public string SapIndex { get; set; } public string SapName { get; set; } }. Then I want to call another Selectus<ProductTypes> for another table etc... So I want to write generic/overall method and use it universally for all types of my objects which reflects the fields of few database tables. The SapIndex property is always in the same place of all objects...
Using prop[1] is incredibly fragile. Who says that the property you're currently interested in is always going to be in second place? What if someone adds another property tomorrow? What if not every T that you use have the same property in the second place on its list of properties? It is quite unclear what your actual goal is here and why you've taken the reflection route.
You would be better off using inheritance or interface implementation here. I'm going to use an interface in this answer, but either would work.
For the sake of clarity, let's assume there is a Code field in all your possible lists, and this is the property you're trying to match with.
Define a reusable interface:
public interface ICodeEntity
{
string Code { get; }
}
Apply your interface to all of the classes that you intend to use for your Selectus method.
public class Person : ICodeEntity
{
public string Code { get; set; }
// And other properties
}
public class Document : ICodeEntity
{
public string Code { get; set; }
// And other properties
}
Add a generic type constraint that limits the use of T only to types that implement your interface.
public static List<T> Selectus<T>(string code)
where T : ICodeEntity
You can now write your code in a way that it relies on the type in question having a Code property, and the compiler will help enforce it.
var db = OrmLiteBaza().Open();
var list = db.Select<T>().ToList();
db.Dispose();
return list.Where(item => item.Code == code).ToList();
Usage examples:
List<Person> peopleWithCodeABC = Selectus<Person>("ABC");
List<Person> documentsWithCodeXYZ = Selectus<Document>("XYZ");
// This will fail if Animal does not implement ICodeEntity
var compilerError = Selectus<Animal>("ABC");
I might not understand fully what you want, but instead of string looking_for you could pass in a Func<,> delegate which acts as a selector.
Something like:
public static List<TField> Selectus<T, TField>(Func<T, TField> selector)
{
var db = OrmLiteBaza().Open();
var select_all_list = db.Select<T>();
db.Dispose();
var list_selected_record = select_all_list.Select(selector); // 'using System.Linq;'
return list_selected_record.ToList();
}
Then I believe it could be called like this:
var list_one = Selectus((ProductCodes x) => x.SapIndex);
var list_two = Selectus((ProductTypes x) => x.SapIndex);
var list_three = Selectus((ProductCodes x) => x.SapName);
With this syntax I leave out the <ProductCodes, string> generic arguments to the method since they can be inferred.
Hmm, maybe you want it in the opposite dimension. You could do:
public static List<T> Selectus<T>(Func<T, bool> predicate)
{
var db = OrmLiteBaza().Open();
var select_all_list = db.Select<T>();
db.Dispose();
var list_selected_record = select_all_list.Where(predicate); // 'using System.Linq;'
return list_selected_record.ToList();
}
with:
var list_one = Selectus((ProductCodes x) => x.SapIndex == "ABC");
var list_two = Selectus((ProductTypes x) => x.SapIndex == "ABC");
var list_three = Selectus((ProductCodes x) => x.SapName == "DaName");
or:
var list_one = Selectus<ProductCodes>(x => x.SapIndex == "ABC");
var list_two = Selectus<ProductTypes>(x => x.SapIndex == "ABC");
var list_three = Selectus<ProductCodes>(x => x.SapName == "DaName");
But if it is going to always be the "same" property, like always x.SapIndex (but for different types of x), then Flater's answer looks good.
Otherwise, if you insist, your reflection approach should be possible. Use propety's name, not its index! Let me try:
public static List<T> Selectus<T>(string looking_for)
{
var db = OrmLiteBaza().Open();
var select_all_list = db.Select<T>();
db.Dispose();
const string prop_name = "SapIndex";
var prop = typeof(T).GetProperty(prop_name); // can blow up for bad T
var list_selected_record = select_all_list
.Where(x => (string)(prop.GetValue(x)) == looking_for); // 'using System.Linq;'
return list_selected_record.ToList();
}
with:
var list_one = Selectus<ProductCodes>("ABC");
var list_two = Selectus<ProductTypes>("ABC");
you can change code to return just one element
public static T Selectus<T>(string looking_for)
{
//all select data
var db = OrmLiteBaza().Open();//opening database
var select_all_list = db.Select<T>();//getting all data for <T> object works fine
db.Dispose();
//try to select one row - here I have trouble:
var prop = typeof(T).GetProperties();//properties of passed <T> object
var list_selected_record = from records in select_all_list where prop[1].Name == looking_for select records;//tryin to select one record from <T> object as in looking_for variable
return list_selected_record.FirstOrDefault();//here one record should be returned
}
Inside a recursive function I append elements to a list (IEnumerable) that I gave the function as a parameter.
Somethig like this:
public class FooObject {
private string Name;
private List<FooObject>? Childs;
public void RecursiveFunction(IEnumerable<FooObject> excludeList) {
if (!excludeList.Any(x => x.Name == this.Name))
return;
excludeList = excludeList.Append(this);
foreach (var child in this.Childs) {
child.RecursiveFunction(excludeList);
}
}
}
The problem is that for example in a depth of 3 it appended an element to the list and has no child elements so finishes and goes up to depth 2 again and there the appended element from depth 3 isn't in the list anymore.
Is this behavior intended or do I missunderstand something in the concept of function parameters and pointers?
You assign a different enumerable to the variable excludeList, similar as:
var excludeList = originalList;
excludeList = otherList; // now originalList is not changed, of course
You need to let the method take a real list and use it's Add method
public void RecursiveFunction(List<FooObject> excludeList) {
if (excludeList.Any(x => x.Name == this.Name))
return;
excludeList.Add(this);
foreach (var child in this.Childs) {
child.RecursiveFunction(excludeList);
}
}
If you want to support more collection as just a List<T> you could allow ICollection<T>.
We are writing a data repository and we have a data model that has quite a few fields.
And on the top of that, we have data accessors that return requested field value of the data object with the given id.
However, the problem is that we have to write a method for every single field which results in a ton of boilerplate code that literally differs in the field accessed and sometimes the return value type.
Here is the code:
[Serializable]
struct MyItem
{
public readonly int Id;
public int SomeInt;
public float SomeFloat;
// in real-life scenario there are many more fields here
}
// we need this container because our JSON parser needs one
class MyItemDataList
{
public List<MyItem> Items = new List<MyItem>();
}
class Example
{
readonly MyItemDataList _myList = new MyItemDataList();
public float GetSomeFloat(int id)
{
for (int i = 0; i < _myList.Items.Count; i++)
{
int currentId = _myList.Items[i].Id;
if (id == currentId)
return _myList.Items[i].SomeFloat;
}
return 0; // just so it compiles for the sake of this example
}
public int GetSomeInt(int id)
{
for (int i = 0; i < _myList.Items.Count; i++)
{
int currentId = _myList.Items[i].Id;
if (id == currentId)
return _myList.Items[i].SomeInt; // all of this methods differ only in the field accessed and value type returned
}
return 0; // just so it compiles for the sake of this example
}
// in real-life scenario there are many more fields here
}
One solution would be to write a switch (if-else) statement and simply in addition to id pass also the field requested but that gives us a very long switch and many comparisons (not a big deal but still).
Ideally, what I would like to achieve is some sort of a template method (maybe with use of pointers) that based on the field requested simply shift the pointer to the desired address and returns the bytes that correspond to the requested field. But how to do it in C#?
You can use generics and accept a Func<MyItem, T>. No need to use pointers, which are considered unsafe in C#.
class Example
{
readonly MyItemDataList _myList = new MyItemDataList();
public T GetSomeProperty<T>(int id, Func<MyItem, T> propertySelector)
{
for (int i = 0; i < _myList.Items.Count; i++)
{
int currentId = _myList.Items[i].Id;
if (id == currentId)
return propertySelector(_myList.Items[i]);
}
return default(T);
}
}
Usage:
For example, if you want to get SomeFloat:
GetSomeProperty(someId, x => x.SomeFloat)
The method could also be implemented with LINQ:
public T GetSomeProperty<T>(int id, Func<MyItem, T> propertySelector)
=> _myList.Items.Where(x => x.Id == id)
.Select(propertySelector)
.FirstOrDefault()
Replace the list against a dictionary.
public class MyItemDataList
{
public Dictionary<int, MyItem> Items { get;} = new Dictionary <int, MyItem>();
}
Create an extension method that accesses the dictionary for convenience
public static MyItem GetItem(this Dictionary<int, MyItem> dictionary, int id) => dictionary.TryGetValue(id, out var item)? item : null;
Usage
var #float = Items.GetItem(2)?.SomeFloat ?? 0.0;
I have a list of object and I want to replace one of the objects in the list with the new object:
public Parent AppendParentChildren(Request request)
{
var Children = request.Parent.Children.ToList();
if (Children.Any(x => x.TrackingNumber == request.Child.TrackingNumber))
{
//Here I want to replace any Children that have the same tracking number in the list with the new Child passed in
}
else
{
Children.Add(request.Child);
}
request.Parent.Children = Children;
return request.Parent;
}
public class Request
{
public Parent Parent { get; set; }
public Child Child { get; set; }
}
public class Parent
{
public IEnumerable<Child> Children {get;set;}
}
If I try and use it in a loop:
public static class Extension
{
public static void Update<T>(this List<T> items, T newItem)
{
foreach (var item in items)
{
//this
item = newItem;
}
}
}
item is read only, so I cannot replace the object in the list.
Any suggestions?
You can't change the member of a foreach iteration because foreach implements the IEnumerable type which is read-only.
A solution would be to cast the list of items inside the extension method as a List (which is read-writable). Then you'd want to identify which item(s) in the list you are replacing and update them. Below is what the Update extension method would look like (assuming you're in a situation where you can use LINQ)
public static class Extension
{
public static void Update<T>(this List<T> items, T newItem)
{
var childList = items as List<Child>;
var newChildItem = newItem as Child;
var matches = childList.Where(x => x.TrackingNumber == newChildItem.TrackingNumber).ToList();
matches.ForEach(x => childList[childList.IndexOf(x)] = newChildItem);
}
}
I've put a working example (albeit slightly bloated) on dotnetfiddle
https://dotnetfiddle.net/MJ5svP
It's also worth noting that although it looks like you're altering childList, this is actually referenced back to the original list not creating a copy (more info on this here)
I need to make some changes so that I only retrieve one object at a time from my list instead of the entire list as I do now.
Right now ive got a private list in class B with a property returning the entire list basically making it public anyway and I want to change this.
The way class a looks(the ui class operating with the list) is, I enter some data validate it and send it to class B which in turn packages it into a list of objects based on the input.
Then class A needs to loop this list and add it to a listview for displaying it which looks like this at the moment:
ListViewItem lvi = new ListViewItem();
foreach ([Object] o in CLassB.getList())
{
lvi = new ListViewItem(o.property0);
lvi.SubItems.Add(o.property1);
lvi.SubItems.Add(o.property2);
lvi.SubItems.Add(o.property3);
}
}
Object is my abstract class which controls how the different types of items are added and getList() is my method in class B returning the entire list.
The thing is these propertys are the common ones all classes share the there are some that arent, like a textbox that you enter specific text about the object and so on which is displayed like this:
private void lvRegistered_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
if (Listview.SelectedItems.Count > 0)
{
foreach ([Object] ob in ClassB.getList())
{
if (Listview.SelectedItems[0].SubItems[0].Text == ob.id.ToString())
{
TextBox.Clear();
TextBox.Text = ob.property4;
}
}
}
}
Now this all works great at the moment but now I have a returned list to operate on but I dont want to return the list making it public I want to return one object of the list based on an index number (yes the functionality will be exactly the same, I made a method returning the count of the private list so I can loop over it and return all). This is for practicing OOP for when I dont want to return everything.
How would this be done? All I can think of is making a new list, take an int as input and search my private list and find the index then add that to the other list and return that list, but I dont know if this is good practice or the best way to do it? Well I havent looked into how to "copy" one element over to next list either but might aswell check and see if theres a better way to do things?
Just get the feeling im "taking the long way around" this way
Not sure to understand, but how about a simple GetById method?
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Test
{
private List<Foo> list = new List<Foo>();
public void Add(Foo foo)
{
this.list.Add(foo);
}
public Foo GetById(int id)
{
return this.list.FirstOrDefault(z => z.Id == id);
}
}
....
Test test = new Test();
test.Add(new Foo { Id = 1, Name = "1" });
test.Add(new Foo { Id = 2, Name = "2" });
test.Add(new Foo { Id = 3, Name = "3" });
Foo foo2 = test.GetById(2);
I'm not sure I understand completely, but it sounds like you could resolve this be creating an indexer on class B to return the item you want:
public object this[int index] {
get {
return list[index];
}
}
change 'object' to whatever your class type actually is.
You can then access the items as if class B was an array:
object item = classB[5];
1) You can use List.AsReadOnly() Method.
public ReadOnlyCollection<Double> MyList {
get {
return myList.AsReadOnly();
}
}
private List<Double> myList;
2) Use index method in the class.
public Double this[int index] {
get {
return myList[index];
}
set {
myList[index] = value;
}
}
private List<Double> myList;
Did about the same as suggested by Ken2k but instead I went with this:
public [Class] getListItem(int index)
{
return myList.ElementAt(id);
}
which in turn is used in my other class that displays the info like:
for (int i = 0; i < am.getCount(); i++)
{
ListViewItem = new ListViewItem([class reference].getList(i).[property].ToString());
ListViewItems.SubItems.Add([class reference].getList(i).[property]);
}
Thanks everyone for all your help on this.