I have a constructor that has a similar signature to ExampleObject(string name, params object[]).
My usual procedure of passing items to this constructor is:
var thisObject = new ExampleObject("name", obj1, obj2, obj3);
Is there anyway I can initialize a separate array of objects, and pass that array to the constructor IN Addition to how I normally do it, by means of LINQ or some other magic?
Ideal result:
object[] specialObjects = {new object("specObj1"), new object("specObject2")}
var thisObject = new ExampleObject("name", obj1, obj2, specialObjects...
Would I need to use LINQ's Enumerable, ForEach, or something I'm completely unaware of, or is something like this not feasible and I should include obj1 and obj2 into specialObjects?
The params keyword is just syntactic sugar for the creation of an array - you could as well do it with an array literal, i.e.
var thisObject = new ExampleObject("name", new [] {obj1, obj2, obj3});
Once you look at it this way, you realize that it is not possible to use an array for part of the parameter list. You have to create a new array. You could definitely use LINQ. Here is an example:
var thisObject = new ExampleObject("name",
(new [] {obj1, obj2}).Concat(specialObjects).ToArray());
(Note that there is a performance penalty involved in using code like this as several temporary objects are created. If you are concerned about performance it may be a better idea to create a specialized overload that takes the array and extra parameters).
Related
How can I create a generic method so the return type is either a list or an array?
Now for this method I get this error:
(string, int)[]' must be a non-abstract type with a public
parameterless constructor in order to use it as parameter 'T' in the
generic method 'T TournamentsAnalytics.GetParameters()
private void Test()
{
var parameters = GetParameters<List<(string, int )>>();
var parameters2 = GetParameters<(string, int)[]>();
}
private T GetParameters<T>() where T: ICollection<(string, int)>, new()
{
var parameters = new T
{
("nr1", 1),
("nr2", 2),
("nr3", 3),
("nr4", 4),
("nr5", 5),
("nr6", 6)
};
return parameters;
}
You probably should not use generics for this. You could for example just use LINQ to convert a sequence of values to a list or an array:
GetParameters().ToList();
GetParameters().ToArray();
...
private IEnumerable<(string, int)> GetParameters(){
yield return ("nr1", 1);
yield return ("nr2", 2);
...
This seem like it is both much shorter and simpler than messing around with generics. Or just return either a list or an array, and use LINQ to convert to the other type if needed, for small lists created infrequently any inefficiencies will be irrelevant.
There might be ways to use generics if you have some specific issue to solve, For example delegating the creation of the collection to the caller by injecting a delegate: Func<IEnumerable<(string, int)>, T), but it will likely just make things more complicated.
Note that your example uses a collection initializer, and this will just not work with arrays, since this initializer uses the Add-method, and this will just not work for arrays.
The constructor of the Array class is private, and as a result you can't pass an array type into a method with a generic new() constraint.
Arrays can still be created in a few ways using the new keyword:
var cars = new Car[3]; // no Car objects created (yet)
var cars = new[] { new Car(), new Car() }; // initialized
var cars = new Car[] { new Car(), new Car() }; // initialized
This is special syntax for arrays, and you'll see that the syntax is also different from what you are trying to make work in the generic method.
I am assuming that the new calls are converted by the compiler to call the static Array.CreateInstance method (which then calls the private constructor), followed by initializing the entries as needed.
Am I misunderstanding what ConvertAll does or just not understanding something, because I took it to be change the type and not just cast.
So I'm wondering how a StringBuilder (or any class) can be converted to another base class (or in this case object) and still keep its data and type.
StringBuilder[] y = new StringBuilder[] { new StringBuilder("a"), new StringBuilder("b"), new StringBuilder("c") };
object[] objectArray1 = Array.ConvertAll<StringBuilder, object>(y, (x2) => (object)x2);
In the above, the new array is of objects, but still contains StringBuilder items. I thought the new array would be of the new type, so essentially lose all the original data, e.g. converting from int to string via a conversion would give you a brand new array of strings.
As in,
string[] array2 = Array.ConvertAll(array1,
element => element.ToString());
Would give you a new array of strings.
thanks.
What ConvertAll() does is change the type of the reference. So you have a StringBuilder reference, and you copy that reference to a variable of type object:
var builder = new StringBuilder();
builder.AppendLine("Hello, World!");
object converted = (object)builder;
Now converted holds an object reference, but the actual object it's pointing to still is the StringBuilder that you instantiated.
The same is happening in the delegate you create. You can't just cast something to a base class and "cut off" all parts that aren't in the base class.
If you have a scenario where you think you need this, create a custom conversion.
I have a question about Enumerable.Repeat function.
If I will have a class:
class A
{
//code
}
And I will create an array, of that type objects:
A [] arr = new A[50];
And next, I will want to initialize those objects, calling Enumerable.Repeat:
arr = Enumerable.Repeat(new A(), 50);
Will those objects have the same address in memory?
If I will want to check their hash code, for example in that way:
bool theSameHashCode = questions[0].GetHashCode() == questions[1].GetHashCode();
This will return me true, and if I will change one object properties, all other objects will change it too.
So my question is: is that properly way, to initialize reference type objects? If not, then what is a better way?
Using Enumerable.Repeat this way will initialize only one object and return that object every time when you iterate over the result.
Will those objects have the same address in memory?
There is only one object.
To achieve what you want, you can do this:
Enumerable.Range(1, 50).Select(i => new A()).ToArray();
This will return an array of 50 distinct objects of type A.
By the way, the fact that GetHashCode() returns the same value does not imply that the objects are referentially equal (or simply equal, for that matter). Two non-equal objects can have the same hash code.
Just to help clarify for Camilo, here's some test code that shows the issue at hand:
void Main()
{
var foos = Enumerable.Repeat(new Foo(), 2).ToArray();
foos[0].Name = "Jack";
foos[1].Name = "Jill";
Console.WriteLine(foos[0].Name);
}
public class Foo
{
public string Name;
}
This prints "Jill". Thus it shows that Enumerable.Repeat is only creating one instance of the Foo class.
When using the following code to create an array:
var foos = Enumerable.Repeat(new Foo(), 2).ToArray();
The reason why each location in the array is the same is because you are passing an object, and not a function that creates an object, the code above is the same as:
var foo = new Foo();
var foos = Enumerable.Repeat(foo , 2).ToArray();
The reason above also explains why using a Select statement, like in the code below, creates a new object for each entry, because you are passing a function that dictates how each object is created, rather than the object itself.
Enumerable.Range(1, 2).Select(i => new Foo()).ToArray();
I would use a simple for loop to populate an array with new reference types.
Ive just seen a piece of code that uses a generic list class to instantiate itself in the following manner:
var foo = new List<string>(){"hello", "goodbye"};
The curly braces after the contructor are especially confusing. It reminds me somewhat of
var bar = new string[]{"hi","bye"};
but in the past i've wouldve always used:
var foo = new List<string>(new []{"hello", "goodbye"});
Has anybody got a link explaining the syntax in the first line of code? I wouldnt even know where to begin with googling it.
As others have pointed out, that is a collection initializer. Some other features you might not be aware of that were added to C# 3:
A collection initializer constructor may omit the parentheses if the argument list is empty. So new List<int> { 10, 20, 30 } is fine.
An array initialized with an array initializer may in some cases omit the type. For example, var myInts = new[] { 10, 20, 30}; infers that myInts is int[].
Objects may be initialized using a similar object initializer syntax. var c = new Customer() { Name = "Fred" }; is the same as var temp = new Customer(); temp.Name = "Fred"; var c = temp;
The point of these features is to (1) make more things that used to require statements into things that require only expressions; LINQ likes things to be expressions, and (2) to enable richer type inference, particularly for anonymous types.
Finally: there has been some confusion in some of the answers and comments regarding what is required for a collection initializer. To be used with a collection initializer the type must (1) implement IEnumerable (so that we know it is a collection) and (2) have an Add method (so that we can add stuff to it.)
See
http://blogs.msdn.com/b/madst/archive/2006/10/10/what-is-a-collection_3f00_.aspx
for additional thoughts on the design of the feature.
here you go. The keyword is "Array Initializers".
http://msdn.microsoft.com/en-us/library/aa664573(v=vs.71).aspx
or rather "Collection Initializers"
http://msdn.microsoft.com/en-us/library/bb384062.aspx
This is a collection initializer: http://msdn.microsoft.com/en-us/library/bb384062.aspx
The type so initialized must implement IEnumerable and have an Add method. The items in the curly-brace list are passed to the add method; different items in the list could be passed to different Add methods. If there's an Add overload with more than one argument, you put the multiple arguments in a comma-separated list enclosed in curly braces.
For example:
class MyWeirdCollection : IEnumerable
{
public void Add(int i) { /*...*/ }
public void Add(string s) { /*...*/ }
public void Add(int i, string s) { /*...*/ }
//IEnumerable implementation omitted for brevity
}
This class could be initialized thus:
var weird = new MyWeirdCollection { 1, "Something", {5, "Something else"} };
This compiles to something like this:
var temp = new MyWeirdCollection();
temp.Add(1);
temp.Add("Something");
temp.Add(5, "Something else");
var weird = temp;
In his blog post (link posted by Eric Lippert in the comments), Mads Torgersen expresses this concisely:
The list you provide is not a “list of elements to add”, but a “list of sets of arguments to Add methods”. ...[W]e do separate overload resolution against Add methods for each entry in the list.
In the third line of code you provided you are making a new string array, and then passing that string array to the list. The list will then add each of those items to the list. This involves the extra overhead of allocating the array, populating it, and then discarding it.
There is a mechanism for a class to define how to use Collection Initializers to populate itself. (See the other answers) I have never found the need to utilize this for my own classes, but existing data structures such as List, Dictionary, often define them, and they are useful to use.
This is a collection initializer. You can use it on collections with an Add method.
The pair of parentheses before the curly braces is optional.
This is very convenient, because you can use it on collections other than lists, for example on dictionaries:
var x = new Dictionary<int,string> {{1, "hello"}, {2, "world"}};
This lets you avoid a lengthier initialization sequence:
var x = new Dictionary<int,string>();
x.Add(1, "hello");
x.Add(2, "world");
I'm returning a Json'ed annonymous type:
IList<MyClass> listOfStuff = GetListOfStuff();
return Json(
new {
stuff = listOfStuff
}
);
In certain cases, I know that listOfStuff will be empty. So I don't want the overhead of calling GetListOfStuff() (which makes a database call).
So in this case I'm writing:
return Json(
new {
stuff = new List<ListOfStuff>()
}
);
which seems a bit unnecessarily verbose. I don't care what type of List it is, because it's empty anyway.
Is there a shorthand that can be used to signify empty enumerable/list/array? Something like:
return Json(
new {
stuff = new []
}
);
Or have I been programming JavaScript too long? :)
Essentially you want to emit an empty array. C# can infer the array type from the arguments, but for empty arrays, you still have to specify type. I guess your original way of doing it is good enough. Or you could do this:
return Json(
new {
stuff = new ListOfStuff[]{}
}
);
The type of the array does not really matter as any empty enumerable will translate into [] in JSON. I guess, for readability sake, do specify the type of the empty array. This way when others read your code, it's more obvious what that member is supposed to be.
You could use Enumerable.Empty to be a little more explicit:
return Json(
new {
stuff = Enumerable.Empty<ListOfStuff>()
}
);
Although it isn't shorter and doesn't get rid of the type argument.
dynamic is also a better option when dealing with an anonymous type
Enumerable.Empty<dynamic>()
this worked well for me
You might not care what type of list it is, but it matters to the caller. C# does not generally try to infer types based on the variable to which it is being stored (just as you can't create overloads of methods on return type), so it's necessary to specify the type. That said, you can use new ListOfStuff[0] if you want an empty array returned. This has the effect of being immutable (in length) to the caller (they'll get an exception if they try to call the length-mutating IList<T> methods.)
Yes, there is. You have to define an array with as least one element, and use linq to filter the array leaving no elements. Example:
var foo = new
{
Code = 1,
Name = "Bar",
Value = (float?)5.0
};
//use an empty object (or any object) to define the type of the array
var emptyArrayOfFooType = new[] {
new
{
Code = (int)0,
Name = (string)null,
Value = (float?)null
}
}.Where(e => false).ToArray(); //use linq to filter the array leaving no elements
//you can use an existing anonymous type variable too
var anotherEmptyArray = new[] { foo }.Where(e => false).ToArray();
//this array with one element has the same type of the previous two arrays
var fooArray = new[] { foo };
//all arrays have the same type, so you can combine them
var combinedArrays = emptyArrayOfFooType.Concat(anotherEmptyArray).Union(fooArray);
send a generic type?:
List<Object>()
or send an empty object array: new Object[0]
I guess you are talking about C# here. My knowledge is limited in C# but I don't think you can create a new object with no type. Why can't you return a generic new List[] ? (might be mixing Java generics here, am not sure is one can return a generic type list in C#).