I try to do something like this:
public const List<String> METRICS = new List<String>()
{
SourceFile.LOC,
SourceFile.MCCABE,
SourceFile.NOM,
SourceFile.NOA,
SourceFile.FANOUT,
SourceFile.FANIN,
SourceFile.NOPAR,
SourceFile.NDC,
SourceFile.CALLS
};
But unfortunately this doesn't work:
FileStorer.METRICS' is of type 'System.Collections.Generic.List<string>'. A const field of a reference type other than string can only be initialized with null.
How can I solve this problem?
const is for compile-time constants. You could just make it static readonly, but that would only apply to the METRICS variable itself (which should typically be Metrics instead, by .NET naming conventions). It wouldn't make the list immutable - so someone could call METRICS.Add("shouldn't be here");
You may want to use a ReadOnlyCollection<T> to wrap it. For example:
public static readonly IList<String> Metrics = new ReadOnlyCollection<string>
(new List<String> {
SourceFile.LoC, SourceFile.McCabe, SourceFile.NoM,
SourceFile.NoA, SourceFile.FanOut, SourceFile.FanIn,
SourceFile.Par, SourceFile.Ndc, SourceFile.Calls });
ReadOnlyCollection<T> just wraps a potentially-mutable collection, but as nothing else will have access to the List<T> afterwards, you can regard the overall collection as immutable.
(The capitalization here is mostly guesswork - using fuller names would make them clearer, IMO.)
Whether you declare it as IList<string>, IEnumerable<string>, ReadOnlyCollection<string> or something else is up to you... if you expect that it should only be treated as a sequence, then IEnumerable<string> would probably be most appropriate. If the order matters and you want people to be able to access it by index, IList<T> may be appropriate. If you want to make the immutability apparent, declaring it as ReadOnlyCollection<T> could be handy - but inflexible.
You'll need to use a static readonly list instead. And if you want the list to be immutable then you might want to consider using ReadOnlyCollection<T> rather than List<T>.
private static readonly ReadOnlyCollection<string> _metrics =
new ReadOnlyCollection<string>(new[]
{
SourceFile.LOC,
SourceFile.MCCABE,
SourceFile.NOM,
SourceFile.NOA,
SourceFile.FANOUT,
SourceFile.FANIN,
SourceFile.NOPAR,
SourceFile.NDC,
SourceFile.CALLS
});
public static ReadOnlyCollection<string> Metrics
{
get { return _metrics; }
}
You are looking for a simple code, like this:
List<string> tagList = new List<string>(new[]
{
"A"
,"B"
,"C"
,"D"
,"E"
});
Related
Is it possible to create an extension method to return a single property or field in a list of objects?
Currently I have a lot of functions like the following.
public static List<int> GetSpeeds(this List<ObjectMotion> motions) {
List<int> speeds = new List<int>();
foreach (ObjectMotion motion in motions) {
speeds.Add(motion.Speed);
}
return speeds;
}
This is "hard coded" and only serves a single property in a single object type. Its tedious and I'm sure there's a way using LINQ / Reflection to create an extension method that can do this in a generic and reusable way. Something like this:
public static List<TProp> GetProperties<T, TProp>(this List<T> objects, Property prop){
List<TProp> props = new List<TProp>();
foreach (ObjectMotion obj in objects) {
props.Add(obj.prop??);
}
return props;
}
Apart from the easiest method using LINQ, I'm also looking for the fastest method. Is it possible to use code generation (and Lambda expression trees) to create such a method at runtime? I'm sure that would be faster than using Reflection.
You could do:
public static List<TProp> GetProperties<T, TProp>(this IEnumerable<T> seq, Func<T, TProp> selector)
{
return seq.Select(selector).ToList();
}
and use it like:
List<int> speeds = motions.GetProperties(m => m.Speed);
it's questionable whether this method is better than just using Select and ToList directly though.
It is, no reflection needed:
List<int> values = motions.Select(m=>m.Speed).ToList();
A for loop would be the fastest I think, followed closely by linq (minimal overhead if you don't do use closures). I can't image any other mechanism would be any better than that.
You could replace the List<int> with a int[] or initialize the list with a certain capacity. That would probably do more to speed up your code than anything else (though still not much).
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");
If I want an empty enumeration, I can call Enumerable.Empty<T>(). But what if I want to convert a scalar type to an enumeration?
Normally I'd write new List<string> {myString} to pass myString to a function that accepts IEnumerable<string>. Is there a more LINQ-y way?
You can use Repeat:
var justOne = Enumerable.Repeat(value, 1);
Or just an array of course:
var singleElementArray = new[] { value };
The array version is mutable of course, whereas Enumerable.Repeat isn't.
Perhaps the shortest form is
var sequence = new[] { value };
There is, but it's less efficient than using a List or Array:
// an enumeration containing only the number 13.
var oneIntEnumeration = Enumerable.Repeat(13, 1);
You can also write your own extension method:
public static class Extensions
{
public static IEnumerable<T> AsEnumerable<T>(this T item)
{
yield return item;
}
}
Now I haven't done that, and now that I know about Enumerable.Repeat, I probably never will (learn something new every day). But I have done this:
public static IEnumerable<T> MakeEnumerable<T>(params T[] items)
{
return items;
}
And this, of course, works if you call it with a single argument. But maybe there's something like this in the framework already, that I haven't discovered yet.
What's the standard way to get a typed, readonly empty list in C#, or is there one?
ETA: For those asking "why?": I have a virtual method that returns an IList (or rather, post-answers, an IEnumerable), and the default implementation is empty. Whatever the list returns should be readonly because writing to it would be a bug, and if somebody tries to, I want to halt and catch fire immediately, rather than wait for the bug to show up in some subtle way later.
Personally, I think this is better than any of the other answers:
static readonly IList<T> EmptyList = new T[0];
Arrays implement IList<T>.
You cannot add to an array.
You cannot assign to an element in an empty array (because there is none).
This is, in my opinion, a lot simpler than new List<T>().AsReadOnly().
You still get to return an IList<T> (if you want).
Incidentally, this is what Enumerable.Empty<T>() actually uses under the hood, if I recall correctly. So theoretically you could even do (IList<T>)Enumerable.Empty<T>() (though I see no good reason to do that).
You can just create a list:
List<MyType> list = new List<MyType>();
If you want an empty IEnumerable<T>, use Enumerable.Empty<T>():
IEnumerable<MyType> collection = Enumerable.Empty<MyType>();
If you truly want a readonly list, you could do:
IList<MyType> readonlyList = (new List<MyType>()).AsReadOnly();
This returns a ReadOnlyCollection<T>, which implements IList<T>.
Starting with .net 4.6 you can also use:
IList<T> emptyList = Array.Empty<T>();
This does only create a new instance once for every different type you specify as T.
IList<T> list = new List<T>().AsReadOnly();
Or, if you want an IEnumerable<>:
IEnumerable<T> sequence = Enumerable.Empty<T>();
If you want a list whose contents can't be modified, you can do:
ReadOnlyCollection<Foo> foos = new List<Foo>().AsReadOnly();
Construct an instance of System.Collections.ObjectModel.ReadOnlyCollection from your list.
List<int> items = new List<int>();
ReadOnlyCollection<int> readOnlyItems = new ReadOnlyCollection<int>(items);
To expand on Dan Tao's answer, the following implementation can be used in the same way as Enumerable.Empty<T>(), by specifying List.Empty<T>() instead.
public static class List
{
public static IList<T> Empty<T>()
{
// Note that the static type is only instantiated when
// it is needed, and only then is the T[0] object created, once.
return EmptyArray<T>.Instance;
}
private sealed class EmptyArray<T>
{
public static readonly T[] Instance = new T[0];
}
}
Edit: I change the above code to reflect the outcome of a discussion with Dan Tao about lazy versus eager initialization of the Instance field.
What about:
readonly List<T> mylist = new List<T>();
Not sure why you want it readonly; that doesn't make much sense in most scenarios I can think of, though.
I'm working on a problem in C# 2.0/.NET 2.0 where I have a Sortedlist and want to search all the "values" (not the "keys") of this SortedList for a certain substring and count up how many occurrences there are.
This is what I'm trying to do:
{
Sortedlist<string,string> mySortedList;
// some code that instantiates mySortedList and populates it with data
List<string> myValues = mySortedList.Values; // <== does not work
int namesFound = myValues.FindAll(ByName(someName)).Count;
}
Naturally, this doesn't work because mySortedList.Values returns an IList, while "myValues" is a List. I tried "casting" the IList so that it would be accepted by myValues, but it doesn't seem to work.
Of course, I can loop over mySortedList.Values in a "foreach" loop, but I don't really want to do this.
Anyone have any suggestions?
EDIT-1: Ok, well it looks like there isn't a native way to do this easily. I had assumed that I was just missing something, but apparently I'm not. So I guess I'm just going to do a "foreach" over the IList.
Thanks for the feedback everyone! I voted everyone up 1 because I thought all the feedback was good. Thanks again! :-)
EDIT-2: Looks like CMS has the answer I was looking for. The only caveat with this (as Qwertie pointed out) is that there is a potential performance penalty since it involves copying all the values to another List and then searching that list start-to-finish. So for short lists, this answer is effective. Longer lists? well that's up to you to decide...
Since the IList Interface implements IEnumerable, you can actually get a List<T> of values using the List<T> (IEnumerable) Constructor:
List<string> myValues = new List<string>(mySortedList.Values);
You can't cast the Values property to List<string> because it is not a List<string>--it is a Dictionary<TKey, TValue>.ValueCollection.
But if you use LinqBridge (for .NET Framework 2.0 with C# 3.0), this problem is easily solved with LINQ as follows:
SortedList<string, string> m = ...;
int namesFound = m.Values.Where(v => v.Contains("substring")).Count();
(if you're still on C# 2.0, you can use Poor-man's LINQ instead, with slightly more work)
Too bad you're in .Net 2.0. This is exactly what LINQ is for. ;)
You can't really do this, since FindAll() is a member of List. You could create a new List on the mySortedList.Values, but it seems to be a waste, since a new object and underlying array needs to be allocated just to call a function.
I'd just write a utility function in some class for lists called FindAll() and then pass your IList and delegate.
Have you tried SortedList's GetValueList yet? This'll give you back an IList of values.
static void Main(string[] args)
{
string someName = "two";
SortedList<string, string> mySortedList = new SortedList<string,string>()
{
{"key1", "This is key one"},
{"key2", "This is key two"},
{"key3", "This is key three"},
};
int namesFound = mySortedList.Values.Where(i => i.Contains(someName)).Count();
Console.WriteLine(namesFound);
Console.ReadKey();
}
In Framework 2.0, maybe can do this:
static void Main(string[] args)
{
string someName = "two";
SortedList<string, string> mySortedList = new SortedList<string,string>()
{
{"key1", "This is key one"},
{"key2", "This is key two"},
{"key3", "This is key three"},
};
int namesFound = FindAll(mySortedList.Values, someName).Count ;
Console.WriteLine(namesFound);
Console.ReadKey();
}
public static IList<String> FindAll(IList<String> items, string item)
{
List<String> result = new List<string>();
foreach (String s in items)
{
if (s.Contains(item))
{
result.Add(s);
}
}
return result;
}
But that is what you really did not want to do.