Can I create an object in place? What I mean is when I have the following class which takes two parameters
class Foo {
public Foo(int x, int y) {}
}
and the following method which takes a Foo object
public void do(Foo foo) {}
can I then write something like this
do({1,2});
instead of this
do(new Foo(1,2));
This would be especially helpful if Foo had a really long name and was surrounded by several namespaces.
No that is not possible.
However if the problem is long names you could try a using alias directive.
using F = A.Very.Long.Namespace.and.classname.FooBarThing;
// ...
List<Bar> list;
// ...
list.Add(new F(1,2));
see https://msdn.microsoft.com/en-us/library/aa664765(v=vs.71).aspx
Short answer
No you cannot. There's only a construct for property/field initialization, e.g.:
new Foo() { a = 2, b = 3 }.
Longer answer
It could beg the question "why not"? Well, I would consider this scenario:
public class Bar : Foo
{
public Bar(int a, int b) : Foo(a, b) {}
}
// ...
List<Bar> list;
// ...
list.Add({1,2});
Now, you at some point you decide that it's a bit strange to have a 'Bar' there in the list, so you change the signature of the list to List<Foo> list;. Your code will now break, because the other constructor is now the 'default'.
Related
I'm facing a problem that I need to construct one object from multiple types and return to the front end, here is what I want(In C#).
The shape that front end wants is like this
{
...
"props" : // this is the place I need to fill-up.
...
}
For the controller, it's a custom response.
public IActionResult Index()
{
return JohnDoe.Render();
}
Behind the scenes, Render is going to get some data from two places.
public object Foo()
{
return string, int, IEnumerable, instance, etc;
}
public object Bar()
{
return string, int, IEnumerable, instance, etc;
}
I know the return statement is not valid, what I mean is that those are all the possibilities.
And here is eventually what I want.
public object Combine()
{
var foo = Foo();
var bar = Bar();
return foo + bar;
}
Again the return statement is not valid, I want to have a final object that contains both of them. It can be Dictionary<string, object> or anonymous object new {}, or something else does not matter as long as one object has both of them.
Obviously what I have here is not possible to achieve it. Here are the two options I came up with.
Just use a wrapper to wrap them, Here is what I do.
public object Combine()
{
var foo = Foo();
var bar = Bar();
return new { foo, bar };
}
I know I can have a Type rather than an anonymous object, the thing is that this will introduce two keys foo and bar, which I do not want to if possible.
Make the foo and bar only return instance. NO string, int, Array, IEnumerable etc.
If I do it in this way, things get a little bit easier. All I need to do is looping through the properties getting the values and map to either new {} or Dictionary<string, object>. This way I do not need to introduce new keys.
Update : so basically I want to avoid introducing new keys if I can, as I just want to return the original without a wrapper. That's why I came up with option 2, only instance is allowed. Let me know your thoughts, please.
You can use a Tuple:
public Tuple<Foo, Bar> Combine()
{
var foo = Foo();
var bar = Bar();
return Tuple.Create(foo, bar);
}
Or a ValueTuple:
public (Foo, Bar) Combine()
{
var foo = Foo();
var bar = Bar();
return (foo, bar);
}
Also with named fields:
public (Foo foo, Bar bar) Combine()
{
var foo = Foo();
var bar = Bar();
return (foo, bar);
}
Or, as Dennis1679 suggest, make a custom type.
How about option 3)
create a class that acts as a wrapper for Foo and Bar called FooBar ?
public class FooBar
{
public Foo Foo { get; set; }
public Bar Bar { get; set; }
}
Why?
C# is an object-oriented programming language. And it's based on the concept of wrapping pieces of data, and behavior related to that data, into special bundles, called objects, which you construct from a 'blueprint' called a class.
I think this is what you are asking
public sealed class FooBar : Foo, Bar
{
}
Unfortunately this is not possible in C#. But in essence this is what you are doing. You can do the following:
public sealed class FooBar: IFoo, IBar
{
public FooBar(IFoo foo, IBar bar)
{
///Assign its members
}
///Implement its members
}
Is there any simple way to convert/parse many Objects of Class Foo to objects of class Bar, using a member method of class Bar like Bar.loadFromFooObject(Foo classFoo) ?
So if I have those 2 Classes:
class Foo
{
public string var1;
public int var2;
public List<string> var3;
}
class Bar
{
public string var1;
public int var2;
public float var4;
public void loadFromFooObject(Foo fooObj)
{
this.var1 = fooObj.var1;
this.var2 = fooObj.var2;
}
}
So that I can avoid doing:
Foo[] fooObjs = { new Foo(), new Foo(), new Foo()};
Bar[] barObjs = new Bar[fooObjs.Length];
for (int i = 0; i < fooObjs.Length; i++)
{
barObjs[i].loadFromFooObject(fooObjs[i]);
}
And do something like:
Foo[] fooObjs = { new Foo(), new Foo(), new Foo()};
Bar[] barObjs = fooObjs.Parse(loadFromFooObject);
Is something like this possible using C# and/or Linq?
Write a method TransformFooToBar and then use the linq, e.g.,
var barObjs = fooObjs.Select(n => TransformFooToBar(n)).ToArray();
If you really want it to be a method on the Bar class, write an extension method, and then linq looks like this:
var barObjs = fooObjs.Select(n => n.TransformFooToBar()).ToArray();
I use this strategy a lot for any kind of object conversion/mapping:
Create the function for a single object conversion
Create an overload accepting an IEnumerable (usually a List for me) and use LINQ .Select to convert the entire list into. It codes seamlessly since the single object conversion is, by definition, a Func. See this SO answer for more explanation on Funcs.
You can also get fancy with extension methods by creating a few extension methods in a static class. For you case specifically, the extension methods could look like this:
public static class ExtensionMethods
{
public static Bar ToBar(this Foo foo)
{
var bar = new Bar();
bar.loadFromFooObject(foo);
//you could also move the logic to convert from the Bar class in here
return bar;
}
//Overload for a collection of Foos (like Foo[] or List<Foo>)
public static IEnumerable<Bar> ToBars(this IEnumerable<Foo> foos)
{
//Since ToBar is a Func<Foo, Bar>
return foos.Select(ToBar);
//alternate lambda syntax: return foos.Select(foo => foo.ToBar());
}
}
And you would call these methods like this:
var fooList = new List<Foo>();
var barEnumerable = fooList.ToBars();
This something like this, all you need to create a ConvertToBar method which takes a Foo and returns a Bar.
var barObjs = fooObjs.Select(i=>ConvertToBar(i)).ToArray();
My preference (and it is just a personal preference) is to override the explicit cast operator and just cast from one type to the other. Combine that with Kye's answer to handle multiple objects.
So, lets start from code so I can better explain myself. I have MyClass class, which contains an int field, also Foo class contains MyClass as field. I want to get value of int field from MyClass using reflection.
public class Foo
{
public MyClass myClass;
}
public class MyClass
{
public int Integer = 1;
}
When i use
Foo f = new Foo();
foreach(FieldInfo fi in f.GetType().GetFields())
{
//lets say now it enumerating myClass field
foreach(FieldInfo fi2 in fi.FieldType.GetFields())
{
return fi2.GetValue(f); //Here I need to use f.myClass, but I can't
//because it's generic method and I don't know what type I'm currently
//enumerating, so just typing f.myClass won't make it
}
}
The question is how do I get value of f.myClass.Integer?
Thanks in advance,
Paul
Any particular reason why you have to use reflection in this instance? If you're just trying to get at the value of that instance method, you can do the following:
Foo f = new Foo();
var myInt = f.myClass.Integer;
I have a class that implements IComparable. It works but the comparison is static, i.e. it's always the same ordering it achieves. What would be a good method to introduce comparison by a parameter, i.e. if we have:
class Poo : IComparable {
public int A { ... };
public int B { ... };
...
}
IEnumerable<Foo> list = ...;
list = list.Sort(???);
I' d like to order the list with respect to A or B depending on the parameter passed to Sort at the question marks. What's the most efficient way to do that?
At the moment, the best method I've came up with is to declare a couple of methods that I pass to Sort as delegates.
private static int CompareWrtA(Foo foo1, Foo foo2) { ... }
private static int CompareWrtB(Foo foo1, Foo foo2) { ... }
if(withRespectToA)
list = list.Sort(CompareWrtA);
else
list = list.Sort(CompareWrtB);
But it doesn't feel really as the best way. Criticism is welcome.
If you want to simplify that statement you can write it like this:
list.Sort((x,y) => withRespectToA ? CompareWrtA(x,y) : CompareWrtB(x,y));
BTW, Sort method is modifying your list, it doesn't return anything.So you don't need to assign it back to your list.
I have an abstract parent class which child classes that inherit from it. I have another class that contains many List<> types of the different child classes. I then have a method in another class that takes a parameter of List<ParentType> and just calls the methods that are declared abstract.
I'm having a problem using List<T>.Cast<T2> on the lists of the child classes. I'm getting the error:
System.Linq.Enumerable.Cast(System.Collections.IEnumerable)' is a 'method', which is not valid in the given context
Does anybody know how to fix this error? Or do I have to reconstruct a list of type List<ParentType> and recast each item individually?
What I'm trying to do:
public abstract class P {
public int num;
public abstract double addSections();
}
public class A : P {
public int num2;
public A(int r, int n) {
num = r;
num2 = n;
}
public double addSections() { return (double)num + (double)num2; }
}
public class B : P {
public double g;
public B(int r, double k) {
num = r;
g = k;
}
public double addSections() { return (double)num + g; }
}
public class MyClass {
public MyClass() {
List<A> listA;
List<B> listB;
//...
helper(listA.Cast<P>()); //doesn't work
helper(listB.Cast<P>().ToList()); //doesn't work either
}
public void helper(List<P> list) {
//...
}
}
In lieu of actually seeing your code so we can fix it, how about changing the method instead:
public void DoSomething<T>(IEnumerable<T> items) where T : ParentType
{
...
}
Or if you're using C# 4 and .NET 4, this should be fine, as IEnumerable<T> is covariant in T in .NET 4.
public void DoSomething(IEnumerable<ParentType> items)
{
...
}
Do you really need the method to accept a List<ParentType>? After all, if you're going to call:
var parentList = childList.Cast<ParentType>().ToList();
and pass that into the method, then you've got two entirely separate lists by that point anyway.
By the way, another effect of the covariant of IEnumerable<T> is that in .NET 4 you can avoid the Cast call and just call:
var parentList = childList.ToList<ParentType>();
EDIT: Now that you've posted your code, it's simply a matter of not calling the Cast method as a method:
// This...
helper(listB.Cast<P>.ToList())
// should be this:
helper(listB.Cast<P>().ToList())
Now that you've added code, I see two potential problems:
You need to add parentheses when calling Cast e.g.
listA.Cast<P>()
Cast is not some special operator, it's an extension method like anything else.
Are those calls to helper actually at the class level, and not inside another method? That would be a problem too.