Archive
Suggestion: Allow new in C# without giving Type
This is a suggestion I’ve just sent in via Visual Studio’s “Send a frown” feature:
Instead of writing statements like:
List<CultureInfo> result = new List<CultureInfo>();
in C# I’d prefer to be able to write
List<CultureInfo> result = new ();
inside the () one would be able to pass contructor parameters and also they should be able to use
SomeClass v = new (someParam) { someProperty = …, otherProperty = … };
syntax, that is be able to initialize properties of the class
What I mean is that I want to omit the type name after the new, since it is deduced from the type I have given to the new var.
Doing
Type v = new (…){…};
is more general from the alternative of doing
var v = new Type(…){…};
since you would be also able to even do
someCollectionType.Add(new (…){…});
to add a new member to a typed collection
and also would be able to do
SomeMethod(new (…){…})
where the Type would be deduced from the param of the method (obviously if it is not overloaded with more versions with just 1 param)
Update:
In fact, now that I think of it again, the concept of anonymous types in C# could be merged with the suggested one, making the (…) optional if no constructor parameters are to be used (in anonymous types you only give the {…} part with the properties’ initialization).
The compiler would then resort to making a new anonymous type only if it can’t deduce a type from the usage context.
Of course if the (…) part (constructor parameters) are given, it would never try to make an anonymous type if it can’t find a matching type to instantiate with the respective constructor signature to call.
Have uploaded this for voting up at:
Single statement ScaleTransform initialization in both WPF and SL
With Silverlight using a cut-down .NET API, some decisions have been at least ackward, causing Silverlight code to be sometimes unnecesserily more complex than its WPF counterpart and WPF code needing several changes to get ported for Silverlight. In ClipFlair I’ve implemented a WPFCompatibility layer to ease compiling WPF code for Silverlight (and vice-versa too) without source code changes.
One of the missing things from Silverlight is at ScaleTransform class, where only a parameterless constructor is available. That way, whereas in WPF you can construct a ScaleTransform and initialize it in one statement, in Silverlight you need to first construct the transform and then set its X scale and Y scale in two separate (property setter) statements. Obviously this also has a small cost in performance since you end up with 3 method calls instead of a single one.
That is the WPF statement
ScaleTransform t = new ScaleTransform(someXscale, someYscale);
has to be translated in Silverlight to:
ScaleTransform t = new ScaleTransform();
t.ScaleX = someXscale;
t.ScaleY = someYscale;
In WPF_ScaleTransform.cs file at WPF_Compatibility project, I provide two different approaches to aid in more portable code that uses ScaleTransform:
1) The first approach is to create a method named “new_ScaleTransform” that takes X & Y scale parameters and returns a new ScaleTransform object and use it instead of calls to ScaleTransform’s constructor that takes X and Y scale.
public static ScaleTransform new_ScaleTransform(double scaleX, double scaleY) //unfortunately there are is no extension method mechanism for contructors in C# yet (and the ScaleTransform class is sealed so we can’t create descendent class)
{
ScaleTransform result = new ScaleTransform();
result.ScaleX = scaleX;
result.ScaleY = scaleY;
return result;
}
Since WPF_Compatibility uses two separate projects WPF_Compatibility.WPF and WPF_Compatibility.Silverlight that share the same source files (added as file links from a common Source subfolder instead of copied into the projects), there is an extra optimization that I decided to do, using a conditional compilation statement so that in WPF we use more optimal code:
public static ScaleTransform new_ScaleTransform(double scaleX, double scaleY) //unfortunately there are is no extension method mechanism for contructors in C# yet (and the ScaleTransform class is sealed so we can’t create descendent class)
{
#if SILVERLIGHT
ScaleTransform result = new ScaleTransform();
result.ScaleX = scaleX;
result.ScaleY = scaleY;
#else
ScaleTransform result = new ScaleTransform(scaleX, scaleY);
#endif
return result;
}
So, with the above approach one will be able to write in both WPF and Silverlight (assuming they add a “Using WPF_Compatibility;” to the top of their C# source file):
ScaleTransform t = new_ScaleTransform(someXscale, someYscale);
2) The second approach is to create a (static) extension method (called SetScale) for the ScaleTransform class and have that method accept X and Y scale params (apart from the implicit ScaleTransform object), which, after setting X and Y scale, should return the ScaleTransform object so that one can construct a ScaleTransform with the parameterless constructor and daisy chain a call to the SetScale method in the same statement. Since that method returns the ScaleTransform object that was passed to it (after setting X and Y scale to it), the combination behaves like a parametric constructor.
public static ScaleTransform SetScale(this ScaleTransform transform, double scaleX, double scaleY)
//can use this in both WPF and Silveright (the last one misses a parametric
//constructor) to initialize on the same statement on which we construct the
//ScaleTransform
{
transform.ScaleX = scaleX;
transform.ScaleY = scaleY;
return transform; //return the transform so that it can be used in the form
ScaleTransform t = new ScaleTransform().SetScale(scaleX, scaleY)
}
After you import the namespace WPFCompatibility (via the using statement mentioned above), where the WPF_ScaleTransform static class belongs, you can make use of this static extension method like below:
ScaleTransform t = new ScaleTransform().SetValue(someXscale, someYscale);
As an added bonus, an extra extension method is provided to set both the X and Y scale from a single parameter:
public static ScaleTransform SetScale(this ScaleTransform transform, double scale)
{
return transform.SetScale(scale, scale);
}
Update:
In recent versions of C# (not sure if VB.net has such a feature) you can initialize multiple properties for a new instance in a single statement at the time of construction, so I have updated the “new_ScaleTransform” method like below. It still works at both WPF and Silverlight, while both get a single-line statement (the WPF version should still be the fastest, even though both are now one-liners).
public static ScaleTransform new_ScaleTransform(double scaleX, double scaleY)
//unfortunately there are is no extension method mechanism for contructors
//in C# yet (and the ScaleTransform class is sealed so we can't create
//descendent class) { #if SSILVERLIGHT
ScaleTransform result =
new ScaleTransform() { ScaleX = scaleX, ScaleY = scaleY }; #else ScaleTransform result = new ScaleTransform(scaleX, scaleY); #endif return result; }
Why I don’t see static extension support for constructors in C# coming
I was hoping C# would someday add static extension support for constructors too (apart from classic methods), that would help a lot in source-level compatibility layers (for example at my WPF_Compatibility project for WPF syntax in Silverlight, which one can find under the ClipFlair source base).
However, according to :
http://mrpmorris.blogspot.gr/2007/01/net-calling-base-constructors-in-c.html
Anders Hejlsberg (father of Delphi and C#) said in an e-mail:
The problem with Delphi’s model allowing constructors to be called on an already constructed object) is that it makes it impossible to have provably immutable objects. Immutability is an important concept because it allows applications to hand objects to an external party without first copying those objects and still have a guarantee that the objects won’t be modified. If constructors can be called on already constructed objects it obviously isn’t possible to make such guarantees. In Delphi’s case that may be ok since Delphi doesn’t really make type safety guarantees anyway (you can cast any object reference to a pointer-to-something and start poking away), but .NET goes further with type safety and this would be a big hole.
He was replying on why one can’t call an ancestor’s constructor directly in C#, but I guess this covers the case of injecting more constructors into ancestors via the static extension method mechanism of recent C# versions.