Is there a standard C++ equivalent of IEnumerableT in C#?
It isn't needed in C++, and here's why:
C# only supports dynamic polymorphism. So to create a reusable algorithm, you need an interface which all iterators will implement. That's IEnumerator<T>
, and IEnumerable<T>
is a factory for returning an iterator.
C++ templates, on the other hand, support duck typing. That means you don't need to constrain a generic type parameter by an interface in order to access members -- the compiler will look up members by name for each individual instantiation of the template.
C++ containers and iterators have implicit interfaces which is equivalent to .NET IEnumerable<T>
, IEnumerator<T>
, ICollection<T>
, IList<T>
, namely:
For containers:
iterator
andconst_iterator
typedefsbegin()
member function -- fills the need forIEnumerable<T>::GetEnumerator()
end()
member function -- instead ofIEnumerator<T>::MoveNext()
return value
For forward iterators:
value_type
typedefoperator++
-- instead ofIEnumerator<T>::MoveNext()
operator*
andoperator->
-- instead ofIEnumerator<T>::Current
- reference return type from
operator*
-- instead ofIList<T>
indexer setter operator==
andoperator!=
-- no true equivalent in .NET, but with container'send()
matchesIEnumerator<T>::MoveNext()
return value
For random access iterators:
operator+
,operator-
,operator[]
-- instead ofIList<T>
If you define these, then standard algorithms will work with your container and iterator. No interface is needed, no virtual functions are needed. Not using virtual functions makes C++ generic code faster than equivalent .NET code, sometimes much faster.
Note: when writing generic algorithms, it's best to use std::begin(container)
and std::end(container)
instead of the container member functions. That allows your algorithm to be used with raw arrays (which don't have member functions) in addition to the STL containers. Raw arrays and raw pointers satisfy all other requirements of containers and iterators, with this single exception.
What is the simplest way to get generic IEnumerableT from System.Collections.IEnumerable?
Simplest and shortest is with LINQ. You can enumerate it without LINQ:
foreach (T item in IEnumerableCollection)
and this is pretty much what .Cast<T>()
does:
static IEnumerable<TResult> CastIterator<TResult>(IEnumerable source) {
foreach (object obj in source) yield return (TResult)obj;
}
IEnumerableT in C#
Well, the first compiler error I get is that it complains that:
Using the generic type 'System.Collections.Generic.IEnumerator' requires '1' type arguments
This is on line 16, this one:
IEnumerator IEnumerable.GetEnumerator()
Fixing that by adding a using directive for the System.Collections
namespace (tip: place the cursor just after IEnumerator, on the r at the end of the word, and hit Ctrl+. (ctrl + the dot-key), it should suggest you add a "using System.Collections;" directive, do that).
Then it compiles, and runs. Does that match what you expect?
Also, note that you should always post the actual error messages you're getting, this way we're not barking up the wrong tree if there's something else wrong with your code that we're not seeing at first glance.
Additionally, you can simplify this very common implementation of IEnumerable<T>
by calling one of the methods from the other, hence I would simplify the implementation of the second methods like this:
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator(); // this will return the one
// available through the object reference
// ie. "IEnumerator<int> GetEnumerator"
}
this way you only implement the actual enumerator code once.
And finally see Earwicker's answer as well, it shows a better (in my opinion at least) way to write this whole code.
Freely convert between ListT and IEnumerableT
List<string> myList = new List<string>();
IEnumerable<string> myEnumerable = myList;
List<string> listAgain = myEnumerable.ToList();
Why IEnumerableT is defined as IEnumerableout T, not IEnumerableT
More information can be found here.
The out
makes the type parameter covariant. That is, you can use either the type or any derived types. Note that out
only works this way with generics, it has a different meaning when used in method signatures (though you probably already knew that).
Here is the example taken from the referenced page:
// Covariant interface.
interface ICovariant<out R> { }
// Extending covariant interface.
interface IExtCovariant<out R> : ICovariant<R> { }
// Implementing covariant interface.
class Sample<R> : ICovariant<R> { }
class Program
{
static void Test()
{
ICovariant<Object> iobj = new Sample<Object>();
ICovariant<String> istr = new Sample<String>();
// You can assign istr to iobj because
// the ICovariant interface is covariant.
iobj = istr;
}
}
As you can see, the out
in the interface signature allows
you to assign an ICovariant<String>
to an ICovariant<Object>
variable, as String
derives from Object
. Without the out
keyword, you would be unable to do this, as the types would be different.
You can read more about covariance (and the related contravariance) here.
As other answers have pointed out, IEnumerable
was only made covariant in .NET 4. Trying to write code such as:
IEnumerable<Object> strings = new List<string>();
will compile in .NET 4 and later versions, but not in previous versions.
Existing methods to emulate C# concept of deferred IEnumerableT in C++?
I re-read your question and I actually think this can be servicable, but it's definitely not ideal without C++11.
You can consider boost::function<boost::optional<T>()>
(yay Boost) as a range. The semantics of this range are super simple- you invoke it, and when it's finished, it gives back an empty optional instead of a value.
For output operations like push_back
, you can consider a boost::function<void(T)>
that will accept the value and then do whatever you need with it. However generally, these aren't that useful, as most functions can be written as returning a modified range, then the caller can simply use that range directly rather than requiring to take an output range.
Not having lambdas here is a total bitch, but you can look into e.g. Boost.Phoenix/Lambda to help.
Equivalence of Observable.Do for Enumerable
LINQ query operators are generally meant to be free from side-effects. You could just use a foreach
loop to "do" your thing.
Or do it in a Select
or Where
method if you don't care about side effects:
enumerable.Select(x => { /*do something here */ return x; })
For a List<T>
, there is a ForEach
extension method that can be used to execute an Action<T>
for each element.
Are IEnumerableT, TaskT and IDisposable hard coded in the C# compiler?
Sort-of.
The compiler has lists of "special" (used in the type-system / binder) and "well-known" (referenced by generated code) types and members, which are hard-coded by name in Roslyn source. However, all that it cares about are the names & methods / signatures of these types / members; you can still write your own mscorlib (and people have done this) as long as it has them.
See
- http://sourceroslyn.io/#Microsoft.CodeAnalysis/SpecialType.cs
- http://sourceroslyn.io/#Microsoft.CodeAnalysis/SpecialMember.cs
- http://sourceroslyn.io/#Microsoft.CodeAnalysis/WellKnownTypes.cs
- http://sourceroslyn.io/#Microsoft.CodeAnalysis/Symbols/WellKnownMemberNames.cs
LINQ equivalent of foreach for IEnumerableT
There is no ForEach extension for IEnumerable
; only for List<T>
. So you could do
items.ToList().ForEach(i => i.DoStuff());
Alternatively, write your own ForEach extension method:
public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
foreach(T item in enumeration)
{
action(item);
}
}
Related Topics
Razor Syntax Error Serializing ASP.NET Model to JSON with HTML.Raw
Multiple SQL Statements in One Roundtrip Using Dapper.Net
How to Save Dlls in a Different Folder When Compiling in Visual Studio
How to Validate That a String Doesn't Contain HTML Using C#
Auto Create Database Tables from Objects, Entity Framework
C# Null Coalescing Operator Equivalent for C++
Insert Text into the Textbox of Another Application
Onchange Event for HTML.Dropdownlist
Webutility.HTMLdecode Vs Httputilty.HTMLdecode
Open iOS Application from Unity
How to Explain C++ Pointers to a C#/Java Developer
Default Value for Missing Properties with JSON.Net
How to Write Out a Text File in C# with a Code Page Other Than Utf-8
How to Convert Image to Data Uri for HTML with C#
Is Idependencyresolver an Anti-Pattern
C# Fill Combo Box from SQL Datatable
How to Hook into Hardware Keyboard Events at an Application Level