using MyAlias = StaticClass.Method

Topics: C# Language Design
May 27, 2014 at 10:19 AM
The using static class feature is nice. I haven't tried it, but can you alias individual static members of a class as shown in the subject? Would be nice.
May 28, 2014 at 11:15 AM
Doesn't appear so, at least not in the version I downloaded from codeplex, this code:
using Max = System.Math.Max;
gives the error The type name 'Max' does not exist in the type 'System.Math'

this obviously works though:
using System.Math;
...
var max = Max(1, 2);
Is this idea to only pull in individual methods from a static class, rather than the whole class?
May 28, 2014 at 8:15 PM
MattWarren wrote:
Is this idea to only pull in individual methods from a static class, rather than the whole class?
I would guess part of the idea would be to allow the use of free functions. Especially if using could be scoped narrowly, it would seem nicer to say:
PointF Rotate(PointF Src, float Angle)
  using Sin = Math.Sin, Cos=Math.Cos
{
   double ang = Angle * Math.Pi;
   return new PointF((float)(Src.X*Cos(Ang) - Src.Y*Sin(Ang)),
     (float)(Src.Y*Cos(Ang) + Src.X*Sin(Ang)));
}
than
PointF Rotate(PointF Src, float Angle)
{
   double ang = Angle * Math.Pi;
   return new PointF((float)(Src.X*Math.Cos(Ang) - Src.Y*Math.Sin(Ang)),
     (float)(Src.Y*Math.Cos(Ang) + Src.X*Math.Sin(Ang)));
}
The Math. before every Sin or Cos adds visual clutter with nearly zero informative value; moving the Math. outside the expressions that are performing the computation would reduce the clutter there. For this simple example it's not too bad, but it's not uncommon for expressions to have many calls to methods like Sin and Cos, and eliminating the visual clutter can be a plus. Additionally, if the code needs to be migrated on a platform which is using an ARM or other processor that can perform trig functions on a Single more efficiently than Double, it may be helpful to be able to rework the code as:
PointF Rotate(PointF Src, float Angle)
  using Sin = FastApproxMath.Sin, Cos=FastApproxMath.Cos
{
   float ang = (float)(Angle * Math.Pi);
   // Main expression doesn't need to change.  The typecasts which were necessary to satisfy the
   // compiler will be redundant if the approximate functions return `float` instead of `double`, but will
   // be harmless at least in this particular case.
   return new PointF((float)(Src.X*Cos(Ang) - Src.Y*Sin(Ang)),
     (float)(Src.Y*Cos(Ang) + Src.X*Sin(Ang)));      
}
Being able to change one line to substitute different sine and cosine functions within the method would seem nicer than having to use find/replace and hope one doesn't accidentally change something one shouldn't.
Jun 5, 2014 at 3:04 PM
using Sin = Math.Sin
My +1000! Good idea to get rid of boring class specification.
Jun 7, 2014 at 8:40 PM
Edited Jun 7, 2014 at 8:50 PM
This is an excellent proposal. It would reduce the scope and completion list clutter introduced by the otherwise excellent static using feature.

Especially when combined with supercat's suggestion, it could be used to improve both explicitness, brevity, and clarity at the same time.

Consider:
void ProcessException(Exception e)
    using Log = System.Diagnostics.Debug.WriteLine
{
    Log(e.Message);
    Log(e.StackTrace);
    ...
}
Jun 7, 2014 at 10:32 PM
aluanh wrote:
Especially when combined with supercat's suggestion, it could be used to improve both explicitness, brevity, and clarity at the same time.
Not only that, but if it ever becomes necessary to change the code, being able to explicitly create aliases will ensure that things that should change together, do. At times, the fact that two statements do precisely the same thing with different operands may be more important that the exact nature of the actions they performed. In other cases, the optimal action to be performed on one operand may, by sometimes coincidence, happen to be the same as the optimal for the other, but changing requirements may cause that condition to not always hold. Allowing the use of deliberate aliasing will help ensure that the first two actions stay the same, while preventing unwanted aliasing of the latter two.
Sep 9, 2014 at 2:24 PM
This is a nice feature; however I heard on .NET Rocks! about the possibility of adding using for non-static members (that is, a with keyword).

I really want to lobby against that. We used to have that in Delphi, and I'll quote from DelphiBasics:
However be warned that it can surprisingly make your code more difficult to read,
especially when nesting With clauses. More disturbingly, it can create maintenance problems,
where a code change can mean that the wrong target for the 'child' field referenced.
Please don't do this.
Sep 9, 2014 at 3:44 PM
TrueWill wrote:
This is a nice feature; however I heard on .NET Rocks! about the possibility of adding using for non-static members (that is, a with keyword).
Different languages implement with differently. I dislike versions in which the syntax for accessing members of another instance is the same as accessing either one's own members or static methods, but in VB.NET, the With statement doesn't do that. A typical usage would be:
With MyArrayOfRectangles(theIndex)   ' Parentheses for array access
  .X -= .Width \ 2    ' Backslash is VB.NET operator for integer division
  .Y -= .Height \ 2
End With
The C# equivalent would be either:
MyArrayOfRectangles[theIndex].X -= MyArrayOfRectangles[theIndex].Width / 2;
MyArrayOfRectangles[theIndex].Y -= MyArrayOfRectangles[theIndex].Height / 2;
or
(ref rect) =>
{
  rect.X -= rect.Width / 2;
  rect.Y -= rect.Height / 2;
}(ref MyArrayOfRectangles[theIndex]);
I think the VB.NET version is cleaner; my only significant complaint is that there's no way to use the "With" variable itself (e.g. there would be no way I could pass the thing upon whose .X and .Y members are being accessed as a ByRef parameter to another method.
Sep 11, 2014 at 6:13 PM
Edited Sep 11, 2014 at 6:18 PM
supercat wrote:
Different languages implement with differently. I dislike versions in which the syntax for accessing members of another instance is the same as accessing either one's own members or static methods, but in VB.NET, the With statement doesn't do that. A typical usage would be:
With MyArrayOfRectangles(theIndex)   ' Parentheses for array access
  .X -= .Width \ 2    ' Backslash is VB.NET operator for integer division
  .Y -= .Height \ 2
End With
Good point; still, imagine the issues with nested Withs (and people will nest them). The compiler can resolve these, but human readers can be misled.

What's wrong with the following? It's fully supported in C# 4, and the variable is scoped to the block. You also don't have to read to the end to see what the reference is and then jump back up to the beginning (as in your latter example).
{
    var rect = MyArrayOfRectangles[theIndex];
    rect.X -= rect.Width / 2;
    rect.Y -= rect.Height / 2;
}
(Update: I just realized that there is a difference when it comes to structs. I seldom use those, though.)
Sep 11, 2014 at 8:35 PM
TrueWill wrote:
Good point; still, imagine the issues with nested Withs (and people will nest them). The compiler can resolve these, but human readers can be misled.
Dots without preceding identifiers only bind to the innermost With. There is no means of accessing outer ones, though I would like to see a means of defining named aliases (in which case a named alias would bind to the With that defined it).
(Update: I just realized that there is a difference when it comes to structs. I seldom use those, though.)
Many of the people involved with C# seem to hold structure types in disdain because they don't behave like Objects. I consider that unfortunate, since there are times when one doesn't really want an object, but instead wants to pass around a bunch of storage locations stuck together with duct tape. Since structures are bunches of variables stuck together with duct tape, they are a much better fit in such situations than any kind of object would be. They would be even better if the maintainers of C# could recognize unboxed structs as being aggregations of storage locations rather than objects. Doing that consistently might require defining a "dialect" of C# (there are certain situations where the defined behavior for a certain construct makes the construct relatively useless, but because the behavior is defined and someone might theoretically use it, implementing a more useful behavior could represent a breaking change), but it would be unfortunate to have a language be forevermore prevented from implementing a useful behavior, in the interest of preserving a behavior that it's possible nobody really uses.

There are many cases where it is useful for the owner of a piece of information to be able to perform updates "in place". Such updates are semantically clean, safe, and efficient when done on exposed-field structures in accessible storage locations. Updating information stored in immutable types is often less clean and less efficient; updating information in privately-owned mutable objects is convenient and efficient, but information stored in mutable types is difficult to share safely and efficiently. Swift seems to have some very good ideas about how structure types should work; perhaps the C# and .NET teams could learn from it.