Reset()
method on IEnumerator<T>
was a mistake (for iterator blocks, the language spec even demands that this throws an exception)IEnumerable<out T>
and Func<in T, out TResult>
, but not concrete types (like List<T>
).ApplicationException
rather fell out of favor - was that a mistake?Contains
, then Add
), so a collection that synchronizes distinct operations isn't all that useful
System.Collections.Concurrent
types, with TryAdd
, GetOrAdd
, TryRemove
, etc were added in .NET Framework 4.0 - though methods that accept a factory delegate do not guarantee the factory will only be invoked once per key.using
/lock
pattern - perhaps allowing them to share a re-usable (extensible?) syntax; you can simulate this by returning IDisposable
and using using
, but it could have been clearerFoo(SqlConnection! connection)
(that injects a null-check / throw
) would be nice (contrast to int?
etc)
dynamic
, or you can enable it like this
foreach
expansion, meaning that anon-methods/lambdas capture the single variable, rather than one per iteration (painful with threading/async/etc)
TextWriter is a base class of StreamWriter. wtf?
That always confuses me to the extreme.
A small C# pet peev - constructors use the C++/Java syntax of having the constructor be the same name as the class.
New()
or ctor()
would have been much nicer.
And sure, tools such as coderush make this less of an issue for renaming classes, but from a readability POV, New() provides great clarity.
I agree emphatically with this post (for those poo-pooing the lack of ToString, there is a debugger attribute to provide a custom format for your class).
On top of the above list, I would also add the following reasonable requests:
T : new(string)
, or where T : new(string, int)
var e = new Foo(); e { Bar = baz };
Either<T>
" is not, so I'd love some way to declare a closed algebraic type and enforce exhaustive pattern matching on it (basically first-class support for the visitor pattern, but far more efficient); so just take enums, extend them with exhaustive pattern matching support, and don't allow invalid cases,System.IO
classes, like Stream
, are somewhat poorly designed; any interface that requires some implementations to throw NotSupportedException
is a bad design,IList
should be much simpler than it is; in fact, this may be true for many of the concrete collection interfaces, like ICollection
,INotifyPropertyChanged
, that take the field name as a string; you can do this by using an extension method that takes a lambda with a MemberExpression
, ie. () => Foo
, but that's not very efficient,
nameof()
operator for single member names, but it doesn't work in generics (nameof(T) == "T"
instead of the actual type-argument's name: you still need to do typeof(T).Name
)) - nor does it allow you to get a "path" string, e.g. nameof(this.ComplexProperty.Value) == "Value"
limiting its possible applications.IArithmetic
; other useful shared operator interfaces are possible as well,readonly
keyword, and C# 6.0 added read-only auto-properties, though it isn't as stringent as true language support for immutable types and values.That's enough for now I suppose. These are all irritations I've run into in the past week. I could probably go on for hours if I really put my mind to it. C# 4.0 is already adding named, optional and default arguments, which I emphatically approve of.
Now for one unreasonable request:
Pretty please? :-)
I don't understand that you can't do
where T : new(U)
So you declare that generic type T has a non-default constructor.
edit:
I want to do this:
public class A
{
public A(string text)
{
}
}
public class Gen<T> where T : new(string text)
{
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With