C# Equivalent of Java anonymous inner classes with init blocks - c#

In Java, i like to use constructs such as
List<String> list = new ArrayList<String>() {{add("foo");}};
Is there a way to do this in 1 line in C#, too?

This is called a collection initializer and it's part of C# 3.0.
As well as lists, you can initialize collections of more complicated types, so long as they implement IEnumerable and have approprate Add methods for each element in the collection initializer. For example, you can use the Add(key, value) method of Dictionary<TKey, TValue> like this:
var dict = new Dictionary<string, int>
{
{"first", 10 },
{"second", 20 }
};
More details can be found in chapter 8 of C# in Depth, which can be downloaded free from Manning's web site.

I think what you want is an array initializer
List<string> list = new List<string>() { "foo" };
Multiple items should be comma-separated
List<string> list = new List<string>() { "foo","bar","bas"};

You can do it in .NET 3.5 to set property values:
List<string> list = new List<string> () { Property = Value, Property2 = Value2 };
Or to initialize an array:
List<string> list = new List<string> () { "value1", "value2" };
You can't call methods this way, however.

If you just need to deal with adding objects to a collection, then collection initializers work great, but if you need more static initialization to be performed, you can use something called a static constructor that works the same as a static initializer in java
This has poor formatting but seems to cover it

Related

What is the C# equivalent of Java List.of()?

I need a fast way to create immutable Lists in one line just like Java's List.of(), but in C#. What's the equivalent to this syntax?
List<String> strings = List.of("first", "second");
You could use ImmutableList.Create
ImmutableList<string> list = ImmutableList.Create("first", "second");
You could also use AsReadOnly which returns a wrapper for the list:
ReadOnlyCollection<string> readonlyList = new List<string> { "first", "second" }.AsReadOnly();
However, as this is just a wrappper you can always modify the underlying list, so it's not truly immutable.
Try this code:
var strings = new List<string> { "first", "second" };

Is there any subtle difference between inline initializing a list with or without '()'?

E.g. is there any technical difference between invoking:
List<string> list = new List<T> () { "one", "two", "tree" }; // with ()
and
List<string> list = new List<T> { "one", "two", "tree" }; // without ()
?
The result is obviously the same. But I am interested if there is any technical difference in the way of invocation or this is only a convenience .NET C# shortcut.
There is no difference. The parenthesis are not required when using a collection initializer with the default constructor. However, if you want to use another constructor you cannot omit the parenthesis.
Some code refactoring tools like ReSharper will indicate this by showing the parenthesis as redundant.
Collection initializers are not limited to "built-in" .NET types. A type implementing IEnumerable and providing a suitable Add method can use a collection initializer.
Both will actualy compile into
List<string> list;
List<string> temp;
temp = new List<string>();
temp.Add("one");
temp.Add("two");
temp.Add("tree");
list = temp;
if you check generated IL code.

How to initialize a list of strings (List<string>) with many string values

How is it possible to initialize (with a C# initializer) a list of strings? I have tried with the example below but it's not working.
List<string> optionList = new List<string>
{
"AdditionalCardPersonAddressType","AutomaticRaiseCreditLimit","CardDeliveryTimeWeekDay"
}();
Just remove () at the end.
List<string> optionList = new List<string>
{ "AdditionalCardPersonAdressType", /* rest of elements */ };
List<string> mylist = new List<string>(new string[] { "element1", "element2", "element3" });
You haven't really asked a question, but the code should be
List<string> optionList = new List<string> { "string1", "string2", ..., "stringN"};
i.e. no trailing () after the list.
var animals = new List<string> { "bird", "dog" };
List<string> animals= new List<string> { "bird", "dog" };
Above two are the shortest ways, please see https://www.dotnetperls.com/list
Your function is just fine but isn't working because you put the () after the last }. If you move the () to the top just next to new List<string>() the error stops.
Sample below:
List<string> optionList = new List<string>()
{
"AdditionalCardPersonAdressType","AutomaticRaiseCreditLimit","CardDeliveryTimeWeekDay"
};
If you are using C# 9.0 and up you can use the new feature target-typed new expressions Link
Example:
List<string> stringList = new(){"item1","item2", "item3"} ;
The right way to initialize along with declaration is :
List<string> optionList = new List<string>()
{
"AdditionalCardPersonAdressType","AutomaticRaiseCreditLimit","CardDeliveryTimeWeekDay"
};
This is how you initialize and also you can use List.Add() in case you want to make it more dynamic.
List<string> optionList = new List<string> {"AdditionalCardPersonAdressType"};
optionList.Add("AutomaticRaiseCreditLimit");
optionList.Add("CardDeliveryTimeWeekDay");
In this way, if you are taking values in from IO, you can add it to a dynamically allocated list.
Move round brackets like this:
var optionList = new List<string>(){"AdditionalCardPersonAdressType","AutomaticRaiseCreditLimit","CardDeliveryTimeWeekDay"};
One really cool feature is that list initializer works just fine with custom classes too: you have just to implement the IEnumerable interface and have a method called Add.
So for example if you have a custom class like this:
class MyCustomCollection : System.Collections.IEnumerable
{
List<string> _items = new List<string>();
public void Add(string item)
{
_items.Add(item);
}
public IEnumerator GetEnumerator()
{
return _items.GetEnumerator();
}
}
this will work:
var myTestCollection = new MyCustomCollection()
{
"item1",
"item2"
}
There is something else that you might be missing that hasn't been mentioned. I think it might be the problem you are having as I suspect you already tried removing the trailing () and still got an error.
First, like others have mentioned here, in your example you do need to remove the trailing ();
But, also, note that List<> is in the System.Collections.Generic namespace.
So, you need to do one of the following two options:
[#1 below is probably the more preferred option]
(1)
Include the use of the namespace at the top of your code with:
using System.Collections.Generic;
or
(2)
Put the fully qualified path to List in your declaration.
System.Collections.Generic.List optList=new System.Collections.Generic.List
{ "AdditionalCardPersonAddressType","AutomaticRaiseCreditLimit","CardDeliveryTimeWeekDay"
};
Hope that helps.
The error message you receive when you implement List correctly but don't include the System.Collections.Generic namespace is misleading and not helpful:
"Compiler Error CS0308: The non-generic type List cannot be used with type arguments."
PS - It gives this unhelpful error because if you don't specify that you intend to use System.Collections.Generic.List the compiler assumes you are trying to use System.Windows.Documents.List.
I have seen the content tag C#, but if someone could use Java (the same search terms lead here):
List<String> mylist = Arrays.asList(new String[] {"element1", "element2", "element3" }.clone());
This is how you would do it.
List <string> list1 = new List <string>();
Do Not Forget to add
using System.Collections.Generic;

Declaration of Anonymous types List [duplicate]

This question already has answers here:
A generic list of anonymous class
(22 answers)
Closed 8 years ago.
Is there any way to declare a list object of anonymous type. I mean
List<var> someVariable = new List<var>();
someVariable.Add(
new{Name="Krishna",
Phones = new[] {"555-555-5555", "666-666-6666"}}
);
This is because I need to create a collection at runtime.
How about dynamic?
List<dynamic> dynamicList = new List<dynamic>();
dynamicList.Add(new { Name = "Krishna", Phones = new[] { "555-555-5555", "666-666-6666" } });
It involves a bit of hackery but it can be done.
static List<T> CreateListFromSingle<T>(T value) {
var list = new List<T>();
list.Add(value);
return list;
}
var list = CreateListFromSingle(
new{Name="Krishna",
Phones = new[] {"555-555-5555", "666-666-6666"}}
);
You can make a list like this, but you'll again have to use some serious hackery, and you'll have to use some "type by example" situations. For example:
// create the first list by using a specific "template" type.
var list = new [] { new { Name="", Phones=new[] { "" } } }.ToList();
// clear the list. The first element was just an example.
list.Clear();
// start adding "actual" values.
list.Add(new { Name = "Krishna", Phones = new[] { "555-555-5555", "666-666-6666" } });
In general you can use the (arguably bad-smelling) cast by example trick others have mentioned to create instances of any generic type parameterized with an anonymous type for the type argument. However, for List<T> there is a slightly less gross way to do it:
var array = new[] {
new {
Name="Krishna",
Phones = new[] {"555-555-5555", "666-666-6666"}
}
};
var list = array.ToList();
Your sketch of a proposed syntax is similar to a feature we did not implement for C# 3 or 4, but we considered. We call the feature "mumble types", and it would go something like this:
List<?> myList = new List<?>() {
new {
Name="Krishna",
Phones = new[] {"555-555-5555", "666-666-6666"}
}
};
We call it "mumble types" because of course you'd read it "myList is a new list of hrmmf". :-)
The idea is that the compiler would look at the initializers and do its best to figure out what the type could possibly be, just the same way as how "var" means "look at the initializer and figure out what the type of the variable is". Whether we'd use "var" as the "mumble" or "?" (which is similar to what Java does in a related feature), or something else is an open question.
In any event, I wouldn't hold my breath waiting for this feature if I were you. It hasn't made the cut for several language versions so far, but it will stay on the list of possibilities for a while longer I think. If, hypothetically speaking, we were to be designing future versions of the language. Which we might or might not be. Remember, Eric's musings about future versions of C# are for entertainment purposes only.
Here's an approach that is somewhat cleaner than many of the other suggestions:
var list = Enumerable.Repeat(new { Name = "", Phones = new[] { "" } }, 0)
.ToList();
// ...
list.Add(new { Name = "Krishna",
Phones = new[] { "555-555-5555", "666-666-6666" } });
You can't make a collection of an anonymous type like this.
If you need to do this, you'll need to either use List<object>, or make a custom class or struct for your type.
Edit:
I'll rephrase this:
Although, technically, it's possible to make a list of an anonymous type, I would strongly recommend never doing this. There is pretty much always a better approach, as doing this is just making code that is nearly unmaintainable. I highly recommend making a custom type to hold your values instead of using anonymous types.
A custom type will have all of the same capabilities (since anonymous types are defined, by the compiler, at compile time), but will be much more understandable by the developer who follows you...
And just to play, too, here's my entry for "code I'd never actually want to use in the real world":
var customer = new { Name = "Krishna", Phones = new[] { "555-555-5555", "666-666-6666" } };
var someVariable = new[]{1}.Select(i => customer).ToList();
I spent quite a lot of time trying to find a way to save myself some time using a list of anonymous types, then realised it was probably quicker just to use a private class inside the current class...
private class Lookup {
public int Index;
public string DocType;
public string Text;
}
private void MyMethod() {
List<Lookup> all_lookups = new List<Lookup> {
new Lookup() {Index=4, DocType="SuperView", Text="SuperView XML File"},
new Lookup() {Index=2, DocType="Word", Text="Microsoft Word Document"}
};
// Use my all_lookups variable here...
}
I don't think this is possible. Maybe in C# 4 using the dynamic keyword?

C# Function Chaining

Why do i receive error in the following declaration ?
List<int> intrs = new List<int>().AddRange(new int[]{1,2,3,45});
Error :Can not convert type void to List ?
Because AddRange function does not return a value. You might need to perform this in two steps:
List<int> intrs = new List<int>();
intrs.AddRange(new int[]{1,2,3,45});
You could also use a collection initializer (assuming C# 3.0+).
List<int> intrs = new List<int> { 1, 2, 3, 45 };
Edit by 280Z28: This works for anything with an Add method. The constructor parenthesis are optional - if you want to pass thing to a constructor such as the capacity, you can do so with List<int>(capacity) instead of just List<int> written above.
Here's an MSDN reference for details on the Object and Collection Initializers.
Dictionary<string, string> map = new Dictionary<string, string>()
{
{ "a", "first" },
{ "b", "second" }
};
Because AddRange modifies the specified list instead of returning a new list with the added items. To indicate this, it returns void.
Try this:
List<int> intrs = new List<int>();
intrs.AddRange(new int[]{1,2,3,45});
If you want to create a new list without modifying the original list, you can use LINQ:
List<int> intrs = new List<int>();
List<int> newIntrs = intrs.Union(new int[]{1,2,3,45}).ToList();
// intrs is unchanged
AddRange does not return the list it has added items to (unlike StringBuilder). You need to do something like this:
List<int> intrs = new List<int>();
intrs.AddRange(new int[]{1,2,3,45});
AddRange() is declared as:
public void AddRange(object[]);
It does not return the list.
By the way in C# 3.x (not sure about 2.0) you can do either of
List<int> intrs = new List<int>{1,2,3,45};
List<int> intrs = new []{1,2,3,45}.ToList(); // with Linq extensions
Besides other answers, you can add your own extension method that will add range and return list (not that it's a good practice).
BTW, if you had already declared intrs, you could have done it with parentheses:
(intrs = new List<int>()).AddRange(new int[] { 1, 2, 3, 45 });
However, I like the initialization syntax better.
Although others have already mentioned that AddRange does not return a value, based on the samples given for alternatives it should also be remembered that the constructor of List will take an IEnumerable of T as well in addition to the code previously mentioned that is .NET 3.5+
For example:
List<int> intrs = new List<int>(new int[]{2,3,5,7});
There is yet another way.
List<int> intrs = new List<int>
{
1,
2,
3,
45
};

Categories

Resources