I'm working on some code which uses dynamic variables.
dynamic variable;
Behind scenes, this variable contains collection of Shapes which is again collection of dynamic variables.
So code like this working fine:
foreach(var shape in variable.Shapes) //Shapes is dynamic type too
{
double height = shape.Height;
}
I need to get first item height from this collection.
This hack works well:
double height = 0;
foreach(var shape in variable.Shapes)
{
height = shape.Height; //shape is dynamic type too
break;
}
Is there better way to accomplish this?
Because variable is dynamic, you won't be able to evaluate variable.Shapes.First(), since determination of extension methods occurs at compile time, and dynamic invocation occurs at runtime. You will have to call the static method explicitly,
System.Linq.Enumerable.First<TType>(variable.Shapes).Height.
Where TType is the expected type of the items in the enumerable.
Otherwise, use LINQ as others have suggested.
Description
You can use the LINQ method First() or FirstOrDefault()to get the first item.
First() - Returns the first element of a sequence.
FirstOrDefault() - Returns the first element of a sequence, or a default value if the sequence contains no elements.
Sample
using System.Linq;
double height = 0;
// this will throw a exception if your list is empty
var item = System.Linq.Enumerable.First(variable.Shapes);
height = item.Height;
// in case your list is empty, the item is null and no exception will be thrown
var item = System.Linq.Enumerable.FirstOrDefault(variable.Shapes);
if (item != null)
{
height = item.Height;
}
More Information
MSDN - LINQ (Language-Integrated Query)
MSDN - Enumerable.First Method
MSDN - Enumerable.FirstOrDefault Method
Related
I want to get value in my object. When I look my inside of object, I can see my value in Result View IEnumerable. But, I can't get this values.
When I write "value."; just see "ToString, GetType, GetHashCode and Equals". I try GetType and get value but I can't. Because, I haven't name of values. How solve we this problem?
The IEnumerable uses syntactic sugar in the background. IEnumerable I feels like a list but behaves differently. The bigest different is that IEnumerable is lazy evaulated. This means only the requested object will be loaded into the memory. The interface hase a CurrentItem property that is accessed by foreach loop.
Here are some options to access the underlaying value:
User foreach
foreach (var value in myEnumerableCollection)
{
Console.WriteLine(value);
}
Use LINQ
var value = myEnumerableCollection.FirstOrDefault(x => x == someSearchTerm);
Cast the enumartion to a list and use the list methods and use indexers or other list methods to grab the value. A small warning, this will force the collection load every element into the memory. If it is large this may cause some issues. For example loading x million rows of db table with no pagination.
int index = 1;
var value = myEnumerableCollection.ToList()[index];
You can cast your value to IEnumerable T, where T - is your type, for example:
if (value is IEnumerable<int> resultList)
{
foreach (int item in resultList)
{
Console.WriteLine(item);
}
};
Let's say I have a list of employee instances, employeeList. I can iterate through them, like this:
IEnumerator enumerator = employeeList.GetEnumerator();
while (enumerator.MoveNext())
{
Console.Write(enumerator.Current + " ");
}
I have three questions:
I have a general idea about how enumerators work, just like iterators in C++. But I don't understand the MoveNext() method (like itr ++ in C++), because the method first checks the condition (whether it is in the last element). Let's say we use enumerator.Current to access the first element: I think it actually has already "moved" to the next element in the list, as MoveNext() has been called. So shouldn't the object that Current points to actually be the second element in the list?
I think it would make sense that we can access the current element when using enumerator.Current. For example, we should be able to use enumerator.Current.name, just like we can use (*itr).name or itr=>name in C++. However, C# looks like it doesn't implement this kind of functionality. So what's the point of using enumerator.Current?
This question is not related to IEnumerator. I just saw some code like this:
IEnumerable<int> result = GetData() ?? Enumerable.Empty<int>;
As a beginner in C#, I only know the && and || operators. What is ???
Read documentation: "After an enumerator is created, the enumerator is positioned before the first element in the collection, and the first call to MoveNext advances the enumerator to the first element of the collection"
The problem with your code is that you assign the enumerator to a non-generic enumerator variable. That works because the generic IEnumerator<T> interface inherits from the non-generic. But that's also the reason why you can't use properties of the Employee-class since the type is Object. You have to cast enumerator.Current to the correct type first.
Therefore it's better to use the generic version (and dipose it properly with using):
using(IEnumerator<Employee> empEnumerator = employeeList.GetEnumerator())
{
while(empEnumerator.MoveNext())
{
// now empEnumerator.Current is the Employee instance without casting
Employee emp = empEnumerator.Current;
string empName = emp.Name; // ...
}
}
You can also use var which works like a placeholder for the real type in C#:
using(var empEnumerator = employeeList.GetEnumerator())
{ ... }
If all you need is to enumerate the whole collection a foreach is more comfortable:
foreach(Employee emp in employeeList)
{
Console.WriteLine(emp.Name);
}
Initially, the enumerator is positioned before the first element (since an enumerable might be empty). Thus, the first invocation of MoveNext moves it to the first element (or returns false, if the enumerable is empty).
You are using the old, non-generic version of IEnumerator, where Current returns an object. You can cast the object to the concrete type and invoke .name, or, even better, use a type for employeeList which returns a strongly typed IEnumerator<Employee> (such as List<Employee>).
This is the null-coalescing operator.
PS: In the future, please create one SO question per question. 1+2 can be seen as related, but 3 definitely isn't.
PPS: If you just want a space-separated list of employee names, you don't need an explicit loop at all:
var names = String.Join(" ", employeeList.Select(e => e.name));
Use IEnumerable just this way:
foreach (var e in employeeList)
{
Console.Write(e + " ");
}
IEnumerable Interface
Exposes an enumerator, which supports a simple iteration over a non-generic collection.
foreach (var employee in employeeList)
{
// do your stuff here, you have full employee object
Console.WriteLine(employee.FirstName);
}
c# null coalescing operator
The ?? operator is called the null-coalescing operator. It returns the left-hand operand if the operand is not null; otherwise it returns the right hand operand.
How do I remove items from a IEnumerable that match specific criteria?
RemoveAll() does not apply.
You can't; IEnumerable as an interface does not support removal.
If your IEnumerable instance is actually of a type that supports removal (such as List<T>) then you can cast to that type and use the Remove method.
Alternatively you can copy items to a different IEnumerable based on your criteria, or you can use a lazy-evaluated query (such as with Linq's .Where) to filter your IEnumerable on the fly. Neither of these will affect your original container, though.
This will produce a new collection rather than modifying the existing one however I think it is the idiomatic way to do it with LINQ.
var filtered = myCollection.Where(x => x.SomeProp != SomValue);
Another option would be to use Where to produce a new IEnumerable<T> with references to the objects you want removed then pass that to a Remove call on the original collection. Of course that would actually consume more resources.
You can't remove items from an IEnumerable<T>. You can remove items from an ICollection<T> or filter items from an IEnumerable<T>.
// filtering example; does not modify oldEnumerable itself
var filteredEnumerable = oldEnumerable.Where(...);
// removing example
var coll = (ICollection<MyClass>)oldEnumerable;
coll.Remove(item);
You don't remove items from an IEnumerable. It's not possible. It's just a sequence of items. You can remove items from some underlying source that generates the sequences, for example if the IEnumerable is based on a list you can remove items from that list.
The other option you have is to create a new sequence, based on this one, that never shows the given items. You can do that using Where, but it's important to realize this isn't removing items, but rather choosing to show items based on a certain condition.
As everyone has already stated, you can't remove from IEnumerable because that is not what the interface is describing. Consider the following example:
public IEnumerable<string> GetSomeStrings()
{
yield return "FirstString";
yield return "Another string";
}
Clearly, removing an element from this IEnumerable is not something you can reasonably do, instead you'd have to make a new enumeration without the ones you don't want.
The yield keywork provides other examples, for example, you can have infinite lists:
public IEnumberable<int> GetPowersOf2()
{
int value = 1;
while(true)
{
yield return value;
value = value * 2;
}
}
Items cannot be removed from an IEnumerable<T>. From the documentation:
Exposes the enumerator, which supports a simple iteration over a collection of a specified type.
You can cast it and use the List<T>.RemoveAll(Predicate<T> match) this is exactly what you need.
This is how i do,
IEnumerable<T> myVar=getSomeData(); // Assume mayVar holds some data
myVar=myVar.Where(d=>d.Id>10); // thats all, i want data with Id>10 only
How about trying Enumerable.Empty i.e.
T obj = new T();
IEnumerable<T> myVar = new T[]{obj} //Now myVar has an element
myVar = Enumerable.Empty<T>(); //Now myVar is empty
I have a HashSet of generic type UserControl, which can have various UserControl (login, settings). I want to check whether the set contains object of any particular type (say login). If so i want to get that element.
I know its quite easy to do with a loop, but is there any better way?
Unfortunately, you cannot do it without a loop, because you need to try all elements of your collection to check their types. In fact, it does not matter that you have a hash set: it would work the same with a list, or any other enumerable. However, LINQ lets you hide the loop, like this:
var item = hashSet.OfType<DesiredType>().FirstOrDefault();
As #dasblinkenlight says you can use OfType<T>() LINQ method to hide the loop. His answer also uses FirstOrDefault() method so "contains element?" questions is rephrased to "is not null". Another way is to use Count() > 0 after OfType<T>().
var items = hashSet.OfType<DesiredType>();
if (items.Count() > 0) {
DesiredType item = items.First();
...
}
Third way is to put predicate in the FirstOrDefault() method.
var item = hashSet.FirstOrDefault(x =>
x.getType() == typeof(DesiredType)
);
if (item != null) {
...
}
If your set doesn't change that often, you can use GroupBy(func) to reduce computation complexity to O(1). Idea is to build dictionary once and query it instead.
var groups = new Dictionary<Type, IEnumerable<UserControl>>();
foreach(var group in hashSet.GroupBy(x => x.GetType()))
groups.Add(group.Key, group);
.
.
.
if (groups.ContainsKey(typeof(DesiredType)) {
DesiredType item = items.First();
...
}
I'm trying to get a row from my SQL Server database. I don't know how to get it I tried many ways but I coludn't get any good solution.
databasEntities db = new databasEntities();
var medlem = from medlemar in db.medlemar
where medlemar.namn == "Ali"
select medlemar;
Here is my database table Medlemar:
id
namn
losen
epost
medlem will be a collection of objects so you should be able to use foreach or .first on that.
foreach(var m in medlem)
{
var namn = m.namm;
...
}
or
var m1 = medlem.First();
In C#, var is not a typeless type. It is actually a way of implicitly typing objects without having to type out the entire type name.
For example:
var someString = "Any String Value";
and
string someString = "Any String Value";
compile to exactly the same IL.
So in your case, the LINQ is returning an IEnumerable<T> collection, where T is the type of your medlemar object.
Since it is a collection, you need to access it just as you would any other collection. One possibility is using foreach
foreach(var m in medlem)
{
//Do Something
}
Another possibility is calling ToList() and then accessing individual members by index:
var medlemList = medlem.ToList();
var namn = medlemList[i].namn; // where i is some specific index in the collection
Or if you just want to get the first object in the collection, you have several alternatives depending on your use case:
var firstMedlem = medlem.Single();
var firstMedlem = medlem.First();
var firstMedlem = medlem.SingleOrDefault();
var firstMedlem = medlem.FirstOrDefault();
Each of the above do roughly the same thing but will behave differently if the collection has zero or multiple objects.
Single() will return the only object in a collection. If the collection contains multiple objects or zero, an exception will be thrown. Similarly, SingleOrDefault() will throw an exception if there are multiple objects, but will return the value returned by default(T) (usually null, except for when T is a value type).
First() and FirstOrDefault() also behave the same way where First() will throw an exception if the collection is empty and FirstOrDefault() will return the default value. They are different from the Single..() methods in that they will always return the first member if a collection has multiple values.
So basically, FirstOrDefault() will never throw an exception unless the collection itself is null. The other variations will throw an exception in one or more cases depending on the contents of the IEnumerable<T> collection.
I think you need to use FirstOrDefault() something like:
var medlem = from medlemar in db.medlemar
where medlemar.namn == "Ali"
select medlemar;
string nameFromVar = medlem.FirstOrDefault();
There are other options you can use besides FirstOrDefault():
Single returns a single item like FirstOrDefault() but it will throw an exception if there is either none or more than one item.
First also returns a single item, but throw when there is no item.
But in case of the FirstOrDefault() it will return the first item or return null when there is no item or more accurate:
default(TSource) if source is empty; otherwise, the first element in
source.