Can I avoid creating a class here? - c#

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);
}

Related

Populating KeyValuePair from stored procedure with IMultipleResults fails due to parameterless constructor

I'm trying to find a good way to get all my lookups that populate drop down lists in one DB trip and using generics so I don't have to create a bunch of custom classes. I'd like to avoid creating a bunch of custom classes, like Class IntStringPair, Class StringStringPair, Class StringIntPair, etc.
I know C# has KeyValuePair so I tried using that, but it throws the exception: 'System.Collections.Generic.KeyValuePair[System.Int32,System.String]' must declare a default (parameterless) constructor in order to be constructed during mapping.'
I saw this post: KeyValuePair - no parameterless constructor?
but what's odd is it works if I only hit one table, but fails if I use IMultipleResults from a stored procedure.
So this works:
using (MyDataContext db = new MyDataContext(Config.CoreDBConnectionString))
{
return db.MyTable.Select(p => new KeyValuePair<string, string>(p.Field1, p.Field2)).ToList();
}
But this fails:
using (MyDataContext db = new MyDataContext(Config.CoreDBConnectionString))
{
System.Data.Linq.IMultipleResults r = db.GetLookups();
return r.GetResult<KeyValuePair<int,string>>().ToList();
}
If I could get this last one to work then I'd have the best of both worlds, a single DB trip and a genericized solution.
I've also tried Dictionary but I always run into serialization problems. The application I'm working on is old so instead of Entity Framework it uses Linq to SQL.
So is there a way to do this without creating a bunch of classes, preferably something built into C#/.NET that uses generics and allows me to get multiple result sets in one trip?
If you create your own generic pair class, you can use that. I created one with Value1 and Value2 properties, but you could create Key/Value instead if preferred:
public class DBPair<T1, T2> {
T1 v1;
T2 v2;
public DBPair() {
}
public DBPair(T1 v1, T2 v2) {
this.v1 = v1;
this.v2 = v2;
}
public T1 Value1
{
get; set;
}
public T2 Value2
{
get; set;
}
}
NOTE: If you need some of the other capabilities of KeyValuePair, like memberwise equality testing or hashcode generation, you will need to add those methods, or transfer the results into a new KeyValuePair after retrieval.
Then you can use it like so:
using (MyDataContext db = new MyDataContext(Config.CoreDBConnectionString))
return db.GetLookups().GetResult<DBPair<int,string>>().ToList();

C# Tuple of List replace/erase previous data

Thank you for all your messages that really helped me, I finally decide to post here. I just discovered Tuples which allow me to create List of List with other element.
Here is my simplified code :
public class Category { //Classe "Category" comprenant le nom de la category et sa proportion de CIR
public string category_name {get; set;}
public string proportion {get; set;}
}
public static void Main(string[] args)
{
var Projects = new List<Tuple<string, List<Category>>>();
while(...)
{ [...]
var List_Categories = new List<Category>()
while(...)
{ [...]
List_Categories.Add(category_example);
}
Projects.Add(Tuple.Create(nom_projet, List_Categories);
}
}
My "Category" class is just 2 strings. A "project" is a List AND a string (project_name) hence my using of Tuple for this.
1st question : I would have create a class for "project" but I could not find how to put a Tuple as a parameter of a class ? (he do not recognize the "var" type as a parameter)
Then, 2nd question : I have an issue : when the program going on, inside "Projects" (which is a List of "project"), the "project_name" is writting well but the "Category" data is each time replaced by the new one for EVERY index of the list. I do not know how such a thing is possible ...
Thank you very much, I hope you can understand my problem, I am very sorry about my English but it is not my native language. I will reformulate if it's not understandable.
It doesn't seem like you want a tuple as a property in your project class, it seems like what you want is this:
public class Project
{
public string project_name {get; set;}
public List<Category> categories {get; set;}
}
And as Corak mentioned, I think a Dictionary might help with your other issue.
By the way, the reason you can't use var as the type of a property is that it isn't a type -- it's just a shorthand way of declaring a variable without explicitly specifying the type of that variable (the compiler figures it out), but it only works on local variables. You can't use it for a property because the compiler would have no way to figure out what the type of that property is supposed to be. The type of a tuple is Tuple<T1, T2,...> -- for example, your tuples here are Tuple<string, List<Category>>, and you could certainly have a class property of that type if you wanted.
Try using a dictionary instead
public static void Main(string[] args)
{
var Projects = new Dictionary<string, List<Category>>();
while(...)
{ [...]
var List_Categories = new List<Category>()
while(...)
{ [...]
List_Categories.Add(category_example);
}
Projects.Add(nom_projet, List_Categories);
}
}
By creating a tuple on every single loop, you are overwriting previous work. With a dictionary you can simply add to your collection inside of your loops

Inheriting a List<> in c# and overriding the constructor

I'm trying to create a wrapper around List to do some specific things I want, such as compute max min, extract specific values from some elements, etc.
I start with
public struct datum {
public UInt32[] chan;
public UInt64 sample_number;
public UInt32 time;
public UInt32 source_sector;
}
public class dataSet : List<datum> {
bool dirty=true;
....
}
the methods are typically like this (I want to know if the list has been modified as I have a max()/min() function that only parses the data when it has been modified and caches the values to reuse if the List has not been modified)
public new void Add(datum x ) {
base.Add(x);
this.dirty = true;
}
However, I'm not sure how to create a constructor. This syntax does not work.. how can I get this type of behavior?
public dataSet(int count) {
this = (dataSet) new List<datum>(count);
}
I also have this constructor, which seems to work fine (no compilation errors) though untested
public dataSet(List<datum> data) {
this.AddRange(data);
}
I came across a post that said that you should use a Collection and a List is used for speed. Though I need the speed, and I'm not sure why a Collection would be better?
--UPDATE--
I don't want to use linq as you can't create something that computes max/min simultaneously as efficiently as this:
public void recalculateMaxMin() {
foreach (var d in data) {
for (int i = 0; i < 16; i++) {
if (d.chan[i] > max[i]) max[i] = d.chan[i];
if (d.chan[i] < min[i]) min[i] = d.chan[i];
}
}
}
Thnx
I'm trying to create a wrapper around List to do some specific things I want, such as compute max min, extract specific values from some elements, etc.
Don't. Just use LINQ to Objects. That's what it was designed for:
var list = new List<int> { 10, 20, 30 };
var average = list.Average();
var max = list.Max();
// etc
In general, I would advise against deriving from List<T> anyway - that's not what it was designed for. However, if you must, you just chain from one constructor to a base constructor:
public dataSet(int count) : base(count)
{
// Add in any extra code you want to here. Probably none in this case.
// It would execute *after* the base constructor call.
}
See my article on constructors for more information about constructor chaining.
(I'd also strongly advise you to change the name - dataSet doesn't comply with .NET naming conventions, and DataSet would mean something else entirely to most .NET developers.)
You can never ever set "this" to something in C#. I think you are looking for this:
public dataSet(int count)
: base(count)
{ }
However in my opinion you should take a look at "System.Linq" namespace. I think what you are trying to implement has been done before by Microsoft. 'Select', 'Join', 'Where' and many other clauses has been already implemented in Linq. Also you can use "INotifyCollectionChanged" interface to implement the dirty thing.
Here are some references:
INotifyCollectionChanged
Linq
If you realy need to implement a complete List class with a new behavior, implementing "System.Collections.Generic.IList" interface is the only thing that will rock your idea in an advanced and perfect way. It's more customizable than inheriting from the List class and trying to change everything you have no access to.
Hope it helps
Cheers
public dataSet(int count)
: base(count) {
}
You can call the base type's constructor using base()
public dataSet(int count) : base(count)
{
// no need to implement anything here. base(count) will call the base
// type's constructor
}

Is chaining c# to look like jQuery a good idea?

I'm thinking of using extension methods to chain a c# statement to look like jQuery in teh following:
foo foo2 =
new foo().Title(foo1.Title)
.Name(foo1.Name)
.DoSomeStuff()
.DoSomeMoreStuff();
Is this a good/bad idea?
public class foo
{
public string Title {get;set;}
public string Name {get;set;}
public int Age {get;set;}
public foo(){}
}
public static class fooExtension
{
public static foo Title(this foo source, string title)
{
source.Title = title;
return source;
}
//and other extensions
}
Upadate: More explanation as the the "why" I'm considering this.
I have 2 things going on:
I'm getting data from one object and
using it to set the properties of
another.
I need to perform some
action on these properties.
So my initial code looked more like
foo2.bars = foo1.bars;
foo2.RemoveUnderage();
foo2.NotifyPatronsBarsAreFull();
and instead, I thought that it might be more descriptive to write:
foo2.bars(foo1.bars).RemoveUnderage().NotifyPatrons();
Initializers are great, but they also bundle the properties all together and I wanted the property set to be close to the actions on which I would be taking on them.
Anything wrong with using object initializers instead?
new Foo { Title = foo1.Title, Name = foo1.Name }
.DoSomeStuff()
.DoSomeMoreStuff();
Chaining in general is fine (look at LINQ) but object initializers mean you don't need to add methods which look like properties.
I personally like this 'fluent' style of programming. Properly-named methods can look like sentences. I would change yours just a bit:
foo foo2 = new foo()
{
Title = foo1.Title,
Name = foo1.Name
}
.DoSomeStuff()
.DoSomeMoreStuff();
I think it is a bad idea in terms of readability, but that's strictly a personal thing.
Do you mean Fluent interface? In some cases the same way is used in classes in .NET Framework (i.e. StringBuilder or LINQ extension methods). However the fluent interface must be explicitly created and it is a lot of work and usage from another language than C# can be not so pretty. I don't think that creating fluent interface for every class is good way how deliver good software in short time.

C# Dynamic extends a object

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);
}

Categories