is it possible to extends a existing object ?
i have the code
var record = new
{
id,
name
};
and have a list of anonymous objects
var list = new List<object>(){ object1, object2 };
Can i add them later to the object ?
Like something as
foreach (var o in list)
{
record.add(o);
}
that i will get this as result
var record = new
{
id,
name,
object1,
object2
};
In short, no. At least, not with anonymous types. There are two approaches here; dynamic might give you what you want, but is fiddly for combining. Other than that, a basic property bag - even simply Dictionary<string,object> would do. The only difference being that:
obj.id
becomes
obj["id"]
There is a more fundamental problem, though, in trying to combine a list (each of which is largely anonymous) with properties in a single step. You can do this for data-binding purpose via custom property models, but it is... tricky.
What you can do is create a class Extension. It is not possible to add new methods in the runtime, but you can do something like this:
public class OneClass
{
private List<object> items;
public List<object> Items { get { return items; } }
public void AddOne(object item)
{
items.Add(item);
}
}
if you want to extend this class behavior, you can write an extension class. Like this:
public static class OneClassExtensions
{
public void AddMany(this OneClass self, params object[] items)
{
foreach(object item in items)
{
self.Items.Add(item);
}
}
}
This way you can call this extension method from your OneClass objects:
OneClass obj = new OneClass();
obj.AddOne("hello");
obj.AddMany("Hello", "world"); // Extension method
There are some rules to follow:
The extension class must have the `static' modifier
you need to put the `this' prefix before the first argument. This argument would be the object itself.
In order to use this extension class in your code, you must use the namespace that contains that extension class, like `using Some.Namespace.That.Has.An.Extension' in every .cs file where you want to use extension methods.
In case anyone runs into this question in the future, I have recently published a library to do exactly this. You can find it on nuget.org - it's called (unsurprisingly) ObjectExtend.
You can install it by grabbing it from Nuget or via your favourite package manager. You can also check out the source code, a brief introduction, or a detailed overview of how it works.
The short version is - install the package, make sure you import the namespace with using Rophuine.LINQPad.ObjectExtend;, and now you should be able to call .Extend on your objects.
A caveat: this is a great technique for exploratory coding, but I recommend against it for anything which will be maintained or go to production.
Since .net4 you could use ExpandoObject to do stuff like that.
For example:
var objs = new List<ExpandoObject>();
for (var i = 0; i < 10; i++)
{
dynamic eObj = new ExpandoObject();
eObj.Property = i;
objs.Add(eObj);
}
foreach (dynamic obj in objs)
{
obj.Property2 = "bubuValue" + obj.Property;
obj.Property3 = "bubuValue" + obj.Property2;
}
foreach (dynamic obj in objs)
{
Console.WriteLine(obj.Property3);
}
Related
I'm a newbie in the C# and .NET at all.
So, I have a collection that contains objects
private List<object> trains = new List<object>();
...
trains.Add(trains[0]);
trains.Add(trains[1]);
trains.Add(trains[2]);
trains.Add(trains[3]);
trains.Add(trains[4]);
And later in my code I must to input all elements of my collection
I'm trying something like that, but it doesn't work
public void Display()
{
...
for (int i = 0; i<trains.Count; i++)
{
Console.WriteLine(trains[i].Number);
Console.WriteLine(trains[i].Destination);
}
}
Help me please, I'm really dont understand how to input it to the console. I read Microsoft documentation about the "List" but :(
You have a list of objects. And object class doesn't have those members (Number and Destination). If you wanna access them either you need to cast your objects to your type or have a list of Train instead of object.
Currently you are storing your objects in a List<object>, Since your class (probably named) Train inherit from Object, you can store its object in object. You need List<Train> and then you can access each member property like:
private List<Train> trains = new List<Train>();
If you can do that for some reason then you have to explicitly cast your object to Train like:
Console.WriteLine(((Train)(trains[i])).Number);
Assuming this
class Train
{
public int Number { get; set; }
public string Destination { get; set; }
}
And that you are doing something like this:
var t1 = new Train();
t1.Number = 1;
t1.Destination = "somewhere";
var t2 = new Train();
t2.Number = 2;
t2.Destination = "somewhereelse";
trains.Add(t1);
trains.Add(t2);
Than you can output using this:
Train train;
foreach(object t in trains)
{
if ((train = t as Train) != null)
{
Console.WriteLine(t.Number);
Console.WriteLine(t.Destination);
}
}
The advantage of using a list of objects is that you can put "anything" there. Not only "Train". But as pointed by #Chris, foreach do not filter, so you have to filter it yourself.
To access the Train object directly, you will need to cast the generic object to a Train object prior to referencing it's exposed properties. This can be done on the fly, it's not necessary to declare the extra variable myTrain here, however for sake of clarity and readability, I generally do it like this.
public void Display()
{
...
for (int i = 0; i<trains.Count; i++)
{
Train myTrain = (Train)trains[i];
Console.WriteLine(myTrain.Number);
Console.WriteLine(myTrain.Destination);
}
}
Others have mentioned and I would agree, I can think of very few situations where you would NEED to use a:
List<object>();
rather than:
List<Train>();
The only thing that jumps out at me would be if you might be storing non Train objects in the same list with Train objects but I cannot think of a good reason to do something like that off the top of my head.
I am using .NET framework 2.0, and I have a situation where I have a class like:
class MyThing
{
private int val;
private DateTime date;
private Guid id;
public MyThing(..) { ... }
}
The only reason this class exists is because at some point in my code, I need to keep track of a List<MyThing>. However, MyThing doesn't have any real purpose other than as a place to keep my data together in one method, so it feels ugly to create a class for this. I'd rather not create a List<List<object>> because this is ugly too.
Is there another way?
Using a class (or perhaps a struct) is definitely the right way to go. Not sure why you think it feels ugly. That's the purpose. It defines "something" and in this case that something is whatever is represented by those three values that you want to keep a list of
As others have suggested, a class is the right way to go.
Additionally, if you don't want to create a class just for the purpose of grouping these properties together, you might want to take a look at the Tuple class [MSDN]. It was introduced in .NET 4.0, but it wouldn't be hard to recreate in .NET 2.0.
Basically, it is a generic class with a bunch of overloads that lets you group different objects together in a type safe way. Something like this:
public class Tuple<T1, T2, T3>
{
public T1 Item1 { get; set; }
public T2 Item2 { get; set; }
public T3 Item3 { get; set; }
}
Then, you would use it like this:
Tuple<int, DateTime, Guid> myThing = new Tuple<int, DateTime, Guid>();
myThing.Item1 = 42;
myThing.Item2 = DateTime.Now;
myThing.Item3 = Guid.NewGuid();
This might not satifying your requirement to not be ugly, but at least it's reusable.
Why is it ugly? This is perfectly normal.
But I would agree, that by having correct class architecture, you should be able to avoid passing classes only as arguments between methods.
If you test your code with FxCop with 'Microsoft All Rules' then using class the only right way.
Because
List< List< oject>> will generate warning
Tuple is also not a good practice. You do not know what Item1, Item2 in Tuple denote. Also you will not get the IntelliSense of its types.
In either way you are creating reference types so there is no change in performance
MainClass and the inside class has 'has-a' relation which cannot be understood if you use tuple of list of list.
Creating different class is the best practice to increase readability and to keep clean code.
Thanks
If you're using a version of Visual Studio 2008 or better (regardless of whether you're targeting .NET 2.0), you could use anonymous types and do something like this without having to declare a class:
static List<T> CreateList<T>(IEnumerable<T> stuff)
{
return new List<T>(stuff);
}
static IEnumerable<T> SubSet<T>(IEnumerable<T> sequence, Predicate<T> predicate)
{
foreach (var item in sequence)
if (predicate(item)) yield return item;
}
static void Main(string[] args)
{
var list = CreateList(new[]
{
new {val = 1,
date = DateTime.Now,
id = Guid.NewGuid()},
new {val = 2,
date = DateTime.Now.AddDays(1),
id = Guid.NewGuid()}
});
var subset = SubSet(list, item=>item.val == 1);
}
Like we do Session.Add("LoginUserId", 123);
and then we can access Session["LoginUserId"], like an Array, how do we implement it?
You need an indexer:
public Thing this[string index]
{
get
{
// get the item for that index.
return YourGetItemMethod(index)
}
set
{
// set the item for this index. value will be of type Thing.
YourAddItemMethod(index, value)
}
}
This will let you use your class objects like an array:
MyClass cl = new MyClass();
cl["hello"] = anotherObject;
// etc.
There's also a tutorial available if you need more help.
Addendum:
You mention that you wanted this to be available on a static class. That get's a little more complicated, because you can't use a static indexer. If you want to use an indexer, you'd need to access it off of a static Field or some such sorcery as in this answer.
You should use indexers
See the link:
http://msdn.microsoft.com/en-us/library/2549tw02.aspx
Sounds like all you need is a generic dictionary.
var session = new Dictionary<string, object>();
//set value
session.Add("key", value);
//get value
var value = session["key"] as string;
If you want to make this static, just make it a static member in another class.
public static class SharedStorage
{
private static Dictionary<string, object> _data = new Dictionary<string,object>();
public static Dictionary<string, object> Data { get { return _data; } }
}
Then you can access it as such, without having to initialize it:
SharedStorage.Data.Add("someKey", "someValue");
string someValue = (string) SharedStorage.Data["someKey"];
If you want to be more adventurous and are using .NET 4 you can also use an Expando Object, like the ViewBag member available to controllers in ASP.NET MVC 3:
dynamic expando = new ExpandoObject();
expando.UserId = 5;
var userId = (int) expando.UserId;
With the way you usually use the Session variable all you really need is a generic Dictionary collection like this one. You don't really need to write a class. But if you need to add extra functionality and/or semantics you could certainly wrap the collection with a class and just include and indexer.
For other collections check out the Collections.Generic namespace.
I created a class where the main task is get data from the DB and mapping it to some object. The problem is the same class needs to map different datareader to different object. So, what I tried to do is to get out the mapping method using delegates.
Here is part of my code. See the important rows in bold.
public class GetDetails<T>
{
**public delegate void DelegateMapping(T position, IDataReader reader);**
**public DelegateMapping mappingMethod;**
public T Get(T instance)
{
//Get IDs and Add to list
_db.ExecuteReader(storedProcedure.ToString(), CommandType.StoredProcedure, reader =>
{
while ( reader.Read() )
{
**mappingMethod(instance, reader);**
}
}, parameterList.ToArray());
return instance;
}
}
And this is the class which is calling and using the "GetDetails" class
public class PositionDB : DbBase
{
public Position GetPositionDetails(string IDs)
{
GetDetails<Position> getIDs = new GetDetails<Position>(base.db);
getIDs.storedProcedure = StoredProcedure.NET_ADM_GetPositionDetails;
//Set the Delegated Method
**getIDs.mappingMethod = MappingPositionDetails;**
//Set Parameters
getIDs.parameterList.AddInParam("PositionIds", DbType.String, IDs);
//Return the PositionId Collection
return getIDs.Get(new Position());
}
**private void MappingPositionDetails(Position position, IDataReader reader)
{
position.Id = reader["CompPositionId"];
position.Description = reader["Description"];
position.ExpirationDate = reader["ExpirationDate"];
position.Title = reader["Title"];
}**
}
The code is working OK.
The questios are:
Did I use delegate correctly?
This kind of solution can cause problems in the future (performance)?
There is another better solution?
Thank you very much
Sebastian
To specifically answer your questions:
Yes, you did use delegates correctly
Yes, it can cause problems due to concurrency issues while multithreading
I think so, I detailed one possible solution below
I would propose three changes:
Move the delegate call into the method (concurrency issues, one thread could change the mapping delegate while another thread tries to access it, now trying to map a reader to completely different object than provided)
Use the already present generic Action/Func delegates, no need to define your own.
Use lambda expressions to define the mapping, no need for extra methods
Notice: 2 and 3 will need at least .net 3.5.
Employing these two proposals, your code would look like this:
public class GetDetails<T>
{
public T Get (T instance, Action<T, IDataReader> mappingMethod)
{
//Get IDs and Add to list
_db.ExecuteReader(storedProcedure.ToString(), CommandType.StoredProcedure, reader =>
{
while ( reader.Read() )
{
mappingMethod(instance, reader);
}
}, parameterList.ToArray());
return instance;
}
}
Now you can use this method in a multi-threaded environment as well.
Edit
just realized it's just part of the code. I corrected my proposal to take this into account.
Yes (There's some improvements you could make, see 3)
Not performance wise, maybe some issues in discoverability.
I would use polymorphism to eliminate the delegate completely for discoerability. Perhaps using an abstract method/class. Also depending on which .NET version you're developing for you can use lambdas and simpler types.
public Action<Position, IDataReader> Mapping { get; set; }
Then
getIDs.Mapping = (position, reader) =>
{
position.Id = reader["CompPositionId"];
position.Description = reader["Description"];
position.ExpirationDate = reader["ExpirationDate"];
position.Title = reader["Title"];
};
Before posting my question, I would like to tell you that I have no prior experience in .Net technologies and have recently started to learn C# (and WPF). My company is looking to move onto .Net technologies and I am the only one in my team learning it, so have noone apart from you guys to discuss or ask something. So if my questions are too stupid or basic at best, please bear with me.
I was trying to create a generic linked list class to allow creation of linked lists of different types. I wrote the following code and would like to have your advise on whether I have written this code properly or not. Any suggestions to improve the code in any way is most welcome.
Main program
class Program
{
static void Main(string[] args)
{
GenLinkedList<string> list = new GenLinkedList<string>("abc");
list.AddtoList("def");
int i = 0;
string[] arr = new string[10];
list.LinkedList.CopyTo(arr,0);
for (i = 0; i < list.LinkedList.Count; i++)
{
Console.WriteLine(arr[i]);
}
GenLinkedList<int> listInt = new GenLinkedList<int>(1);
listInt.AddtoList(2);
i = 0;
int[] arrInt = new int[10];
listInt.LinkedList.CopyTo(arrInt, 0);
for (i = 0; i < listInt.LinkedList.Count; i++)
{
Console.WriteLine(arrInt[i]);
}
}
}
Class GenLinkedList
public class GenLinkedList<T>
{
private LinkedList<T> _linkedlist;
public GenLinkedList(T a)
{
_linkedlist = new LinkedList<T>();
_linkedlist.AddLast(a);
}
public LinkedList<T> LinkedList
{
get
{
return _linkedlist;
}
}
public void AddtoList(T a)
{
LinkedList.AddLast(a);
}
}
Why not use System.Collections.Generic.LinkedList<T>? You're using it internally in your GenLinkedList<T> already and it's already Generic for you.
It's the Framework Provided Generic Doubly Linked List implementation. Read up on it at:
MSDN - LinkedList(T) Class
If you're creating a Generic Linked List as an exercise, you shouldn't base your implementation of of an existing Generic Linked List. You're really not going to be learning anything by wrapping something that already does exactly what you need to do.
1
A generic linked list implementation already exists in the .NET framework: LinkedList<T>. But you already know that; your code wraps it.
2
OK, so you know that. Why would you wrap it, then? The only functionality you appear to have implemented is AddtoList, which doesn't do anything the LinkedList<T> doesn't already do itself (after all, this is only a thin wrapper around LinkedList<T>.AddLast). What this means is that your GenLinkedList<T> class really doesn't offer the functionality of a linked list; it's basically an add-only collection (which could just as easily have been implemented with a List<T>, or a Stack<T>, or a Queue<T> -- anything, really).
3
Assuming you do have a good reason to wrap a LinkedList<T> (e.g., you're planning to add more functionality down the line that would actually leverage the behavior of a LinkedList<T> and/or -- here's a key ingredient -- you want to restrict the way calling code is able to interact with the list (e.g., no removals)), you really shouldn't expose your LinkedList<T> member at all. The purpose of a wrapper is just that: to wrap. You take an existing class and basically give it a new kind of interface. By exposing the underlying object directly, you cripple your wrapper. Any additional restrictions/validation/logic you have in your wrapper can be bypassed.
So, for example, if you want to be able to copy your list to an array, instead of doing this:
list.LinkedList.CopyTo(arr,0);
You would implement a CopyTo method within your GenLinkedList<T> class (which could simply call _linkedlist.CopyTo) and use that.
But I really think the first question you should be asking yourself is what you want to accomplish by wrapping LinkedList<T> in the first place.
The obvious question is why you don't just use LinkedList<T> directly, although it looks like you're trying to emulate a singly-linked list.
In this case, you should avoid exposing the underlying LinkedList<T> instance, since any client could manipulate it directly. I would also implement IEnumerable<T> which will make your list usable by linq.
I got this from http://msdn.microsoft.com/en-us/library/0x6a29h6.aspx
Works fine with me.
namespace GenLinkedList
{
class Program
{
static void Main(string[] args)
{
GenericList<object> list = new GenericList<object>();
// Add items to list.
list.AddHead("some string here");
list.AddHead(DateTime.Today.ToLongDateString());
list.AddHead(13);
list.AddHead(13.005);
for (int x = 0; x < 10; x++)
{
list.AddHead(x);
}
// Enumerate list.
foreach (object i in list)
{
Console.WriteLine(i + " " + i.GetType());
}
Console.WriteLine("\nDone");
}
}
}
namespace GenLinkedList
{
// type parameter T in angle brackets
class GenericList<T>
{
// The nested class is also generic on T.
public class Node
{
private Node next;
// T as private member data type.
private T data;
// T used in non-generic constructor.
public Node(T t)
{
next = null;
data = t;
}
public Node Next
{
get { return next; }
set { next = value; }
}
public T Data
{
get { return data; }
set { data = value; }
}
}
private Node head;
// constructor
public GenericList()
{
head = null;
}
// T as method parameter type
public void AddHead(T t)
{
Node n = new Node(t);
n.Next = head;
head = n;
}
public IEnumerator<T> GetEnumerator()
{
Node current = head;
while (current != null)
{
yield return current.Data;
current = current.Next;
}
}
}
}