Is it somehow possible to get the reference of the result of an overloaded operator in C# so you don't have to use the "new" keyword to create a temp result (which is returned afterwards)?
Here's an example of a problem I ran into:
public class Stats {
public float someField;
public float someOtherField;
public static Stats operator +(Stats a, Stats b) {
Stats c = new Stats(); // I don't want a new one, can I access operators result directly?
c.someField = a.someField + b.someField;
c.someOtherField = a.someOtherField + b.someOtherField;
return c;
}
/*
// This is what I want to achieve, but it would be cooler if static and with the "+"
public Add(SomeType a) {
someField += a.someField;
someOtherField += a.someOtherField
}
*/
}
public class StatObserver {
public Stats statsToObserve;
public Output() {
print(statsToObserve.someField);
}
}
public class Class {
public Stats firstStats = new Stats();
firstStats.someField = 1.5f;
public StatObserver showStats = new StatObserver();
showStats.statsToObserve = firstStats;
public Stats nextStats = new Stats();
nextStats.someField = 3.4f;
// now the tricky part
firstStats += nextStats; // C# handles the += itself correctly
showStats.Output(); // prints "1.5"
// you have to update the observer to get the new value
// it's kind of stupid, because you have to treat firstStats like a value type buts its not
showStats.statsToObserve = firstStats;
showStats.Output(); // prints "4.9"
}
You can't overload the += operator directly - it is compiled to an add and an assignment. You could mutate the left-hand side as part of the + operator - but that would be evil. An Add method seems to be the cleanest design IMHO.
First things first, as #D.Stanley notes, you can't override +=. You can override +, as you have done, but there is something important to realize about +:
Math operators are non-destructive, that is, they return a result
without modifying the operands
That being said, you could modify the properties of operands in a reference type (which this is), but you shouldn't. So don't. The good news is, your + operation is correct.
Because of this, you have to return a new object (as you do), but when you do the += you assign the local reference to this new object, while leaving the observer's reference pointing at the old object, causing your error.
You probably want to modify the observer directly:
showStats.statsToObserve += nextStats;
Or, you could totally hack it and do this (not recommended):
public static Stats operator +(Stats a, Stats b) {
Stats c = new Stats();
c.someField = a.someField + b.someField;
a.SomeField += b.someField; //AHHHH You just modified an operand!
c.someOtherField = a.someOtherField + b.someOtherField;
a.someOtherField += b.someOtherField; //AHHHH You just did it again!
return c;
}
Note: I like #DStanley's recommendation as well for the solution to this.
Related
I was disappointed to discover that C#'s "with expressions" allow the caller to bypass constructor validations on the record.
Consider:
record AscendingPair {
public AscendingPair(int small, int large)
{
if (small >= large) throw new ArgumentException("");
(Small, Large) = (small, large);
}
public int Small { get; init; }
public int Large { get; init; }
}
[Test]
public void Can_create_an_invalid_pair() {
var valid = new AscendingPair(1, 2);
var invalid = valid with { Small = 3 }; // This does not throw :(
}
Is there a smart workaround that would allow use of with, but still enforce the validation?
The with expression is lowered into something like this (check this on SharpLab):
var temp = valid.<Clone>$(); // you can't actually access this from C#
temp.Small = 3;
var invalid = temp;
This is documented here:
First, receiver's "clone" method (specified above) is invoked and its result is converted to the receiver's type. Then, each member_initializer is processed the same way as an assignment to a field or property access of the result of the conversion. Assignments are processed in lexical order.
Notes:
valid.<Clone$>() just calls the copy constructor of the record (new AscendingPair(valid)).
It is possible to set temp.Small here because you are doing it in the member initialiser list, which is one of the places where you can set init-only properties.
Now it should be clear how exactly the with expression bypasses the check in your constructor.
One way to solve this is to move the check to the init accessors:
record AscendingPair {
public AscendingPair(int small, int large)
{
if (small >= large) throw new ArgumentException("");
(Small, Large) = (small, large);
}
private int small;
private int large;
public int Small {
get => small;
init {
if (value >= large) {
throw new ArgumentException("");
}
small = value;
}
}
public int Large {
get => large;
init {
if (small >= value) {
throw new ArgumentException("");
}
large = value;
}
}
}
There is an important caveat to this fix though: the order of the assignments in the with expression now matters. This is a natural consequence of how the with expression is lowered, with each assignment being "processed in lexical order". For example:
var valid = new AscendingPair(1, 2);
var invalid = valid with { Large = 4, Small = 3 };
is fine, but,
var valid = new AscendingPair(1, 2);
var invalid = valid with { Small = 3, Large = 4 };
throws an exception.
We can't really do anything about this though, because to solve this problem, we would need to move the check to after all the assignments of the with expression have completed, but as far as I know, we can't really know when that is inside the record. The lowered code does not call an extra method or anything like that at the end of the series of assignments.
I am trying to implement observable native data types in C# (float, int, string, List). I should add that I am fairly new to C# and come from a C++ background.
My first thought was to have an observable interface like so:
public interface IObservable {
void registerObserver(IObserver observer);
void deregisterObserver(IObserver observer);
void notifyObservers();
}
And then to create a wrapper for a native data type (for example float) that overloads the operators so it is (mostly) seamless to use:
Float f1 = new Float(0);
Float f2 = f1 + 2;
This would have to be an abstract base class since interfaces can't overload operators.
Then I wanted to create an ObservableFloat which combined both ideas but called notifyObservers on any change to its state. The class using it would see it as a Float and would have no idea it was internally also an Observable.
For this I would normally overload the assignment operator so instead of doing something like:
return new Float(f1.value + f2.value);
It would modify the first instance and return it. But since assignment seems to always change the reference, I would loose my observable and its list of observers on the first assignment operation, right?
I found this post that implements an observer using events in C#: link
This code:
private State _state;
public State MyState
{
get { return _state; }
set
{
if (_state != value)
{
_state = value;
Notify();
}
}
}
Does essentially what I want: when the State variable gets assigned a new value it does the assignment and also calls a function. Is there any way you can think of to achieve this while shielding the using class (Product in the example) from knowing that the variable is an Observable?
I think you should use something fluent-like for flexibility instead of overloading primitive types and their operators just to inject them somewhere it doesn't belong:
public interface INumeric
{
INumeric Add(INumeric num);
INumeric Sub(INumeric num);
INumeric Mul(INumeric num);
INumeric Div(INumeric num);
}
So, for instance you will get something like this inside, if you want to copy primitive types behavior:
public INumeric Sub(INumeric b)
{
var a = this;
return new Numeric(a.Value-b.Value);//obviuously, no notify here
}
And if you want to work with instance in fluent style and notify observers:
public INumeric Sub(INumeric b)
{
var a = this;
a.Value = a.Value - b.Value;//notify 'a' observers or whatever here.
return a;
}
In code it will look like this, and will not break on assignment, but beware of little trick below which can confuse you when working with references (omg it will be impossible to debug):
var a = new Numeric(10);
var b = new Numeric(2);
a = a.Sub(b)//10 - 2 = 8
.Add(a)//8 + 8 = 16
.Add(b);//16 + 2 = 18
And in primitive form:
a = a - b + a + b; //10 - 2 + 10 + 2 = 20
PS:
As you see, it is bad idea to overload primitive types. They just too different in nature from references which can easly shuffle your entire logic.
I'm using the MiscUtils library (thanks Marc G. and Jon S.) and am trying to add a generic Sqrt function to it. The problem can be easily reproduced with this:
class N<T>
{
public N(T value)
{
Value = value;
}
public readonly T Value;
public static implicit operator T(N<T> n)
{
return n.Value;
}
public static implicit operator N<T>(T value)
{
return new N<T>(value);
}
public static T operator /(N<T> lhs, T rhs)
{
// Operator.Divide is essentially a wrapper around
// System.Linq.Expressions.Expression.Divide
return Operator.Divide(lhs.Value, rhs);
}
}
// fails with: No coercion operator is defined
// between types 'System.Double' and 'N`1[System.Single]'.
var n = new Numeric<float>(1f);
var x = Operator.DivideAlternative(n, 1.0);
// this works as the N<T> is first converted to a
// float via the implicit conversion operator
var result = n / 1.0;
Now, I realize why this is happening, but I have not yet been able to think of a way around it. For reference, here is the current Sqrt implementation. I have little experience building expression trees.
public static double Sqrt<T>(T value)
{
double oldGuess = -1;
double guess = 1;
while(Abs(guess - oldGuess) > 1)
{
oldGuess = guess;
// the first evaluated call to DivideAlternative throws
guess = Operator.Divide(
Operator.AddAlternative(guess,
Operator.DivideAlternative(value, guess)),
2);
}
return guess;
}
EDIT: Ok, so I solved this on my own, but in an attempt to keep the question as simple as possible I apparently went too far and spent far too much time answering questions from confused people trying to help.
So, this is the problem in its entirety.
I two classes; one that performs transformations and another which performs statistical analysis of image data (pixels). Let's focus on the latter as the problem is the same:
abstract class ImageStatistics
{
private readonly object _pixels;
public ImageStatistics(object pixelArray)
{
Pixels = pixelArray;
}
// calculate the standard deviation of pixel values
public double CalcStdDev();
}
The array of pixels can be any numeric type. In practice, it will be either float, int, ushort, or byte. Now, because generics cannot do things like this:
public T Add<T>(T lhs, T rhs)
{
return lhs + rhs; // oops, no operator + for T
}
I cannot perform any sort of statistical analyses on the pixel values themselves without casting to the proper array type. So, I need to have N sub-classes of ImageProcessor to support N pixel types.
Well, that sucks. I would love to just have a generic ImageProcessor<T> class which has a T[] of pixel data. So, I looked into the MiscUtils library which would allow just this.
Math.Sqrt needs a double, so why not just provide it with one?
public static double Sqrt<T>(T value)
{
return Math.Sqrt(Convert.ToDouble(value));
}
You might also consider casting to dynamic.
public static double Sqrt<T>(T value)
{
return Math.Sqrt((dynamic) value);
}
This technique can also be used for operators like addition:
public static T Add<T>(T a, T b)
{
return (dynamic) a + (dynamic) b;
}
Console application creating array of objects (unknown types) and calculating square route (double)
using System;
namespace GenericSqrt
{
class Program
{
static void Main(string[] args)
{
var array = new object[] { "2", null, 4.1f, 4.444D, "11.3", 0, "Text", new DateTime(1, 1, 1) };
foreach (var value in array)
{
try
{
Console.WriteLine(Sqrt(value));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Console.ReadLine();
}
private static double Sqrt(object value)
{
double converterValue = Convert.ToDouble(value);
return Math.Sqrt(converterValue);
}
}
}
Output looks like this:
1.4142135623731
0
2.02484564958235
2.10807969488822
3.36154726279432
0
Input string was not in a correct format.
Invalid cast from 'DateTime' to 'Double'.
If type is indeed any of number types, as you stated, there is no problem to solve.
Let me preface this by saying it probably isn't worth the effort, considering how this code would need to be maintained. I wrote this in about 10 minutes, so don't expect anything too spectacular.
// You'll need this
public interface ISquareRootHelper
{
double Sqrt<T>(T value)
where T : struct;
}
class Program
{
private static ISquareRootHelper helper;
// Build the helper
public static void BuildSqrtHelper()
{
// Let's use a guid for the assembly name, because guid!
var assemblyName = new AssemblyName(Guid.NewGuid().ToString());
// Blah, blah, boiler-plate dynamicXXX stuff
var dynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
var dynamicModule = dynamicAssembly.DefineDynamicModule(assemblyName.Name);
var dynamicType = dynamicModule.DefineType("SquareRootHelper");
// Let's create our generic square root method in our dynamic type
var sqrtMethod = dynamicType.DefineMethod("Sqrt", MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual);
sqrtMethod.SetReturnType(typeof(double));
// Well, I guess here is where we actually make the method generic
var genericParam = sqrtMethod.DefineGenericParameters(new[] {"T"});
genericParam[0].SetGenericParameterAttributes(GenericParameterAttributes.NotNullableValueTypeConstraint);
// Add a generic parameter, and set it to override our interface method
sqrtMethod.SetParameters(genericParam);
dynamicType.DefineMethodOverride(sqrtMethod, typeof(ISquareRootHelper).GetMethod("Sqrt"));
// Magic sauce!
var ilGenerator = sqrtMethod.GetILGenerator();
// Math.Sqrt((double)value);
ilGenerator.Emit(OpCodes.Ldarg_1); // arg_0 is this*
ilGenerator.Emit(OpCodes.Conv_R8);
var mathSqrtMethodInfo = typeof(Math).GetMethod("Sqrt");
ilGenerator.EmitCall(OpCodes.Call, mathSqrtMethodInfo, null);
ilGenerator.Emit(OpCodes.Ret);
// Since we're overriding the interface method, we need to have the type
// implement the interface
dynamicType.AddInterfaceImplementation(typeof(ISquareRootHelper));
// Create an instance of the class
var sqrtHelperType = dynamicType.CreateType();
helper = (ISquareRootHelper)Activator.CreateInstance(sqrtHelperType);
}
public static void Main(string[] args)
{
BuildSqrtHelper();
Console.WriteLine(helper.Sqrt((short)64)); // Works!
Console.WriteLine(helper.Sqrt((ushort)64)); // Works!
Console.WriteLine(helper.Sqrt((int)64)); // Works!
Console.WriteLine(helper.Sqrt((uint)64)); // Works*!
Console.WriteLine(helper.Sqrt((byte)64)); // Works!
Console.WriteLine(helper.Sqrt((sbyte)64)); // Works!
Console.WriteLine(helper.Sqrt((float)64)); // Works!
Console.WriteLine(helper.Sqrt((double)64)); // Works!
Console.WriteLine(helper.Sqrt((long)64)); // Works!
Console.WriteLine(helper.Sqrt((ulong)64)); // Works*!
// Let's try non-primitives!
Console.WriteLine(helper.Sqrt(DateTime.Now)); // Doesn't fail, but doesn't actually work
Console.WriteLine(helper.Sqrt(Guid.NewGuid())); // InvalidProgramException!
}
}
Anyway, I guess this proves it can be done. Just make sure when you use it, you only pass in primitive types, otherwise all fail will break loose. Actually, it will only throw an exception when you pass in a struct that is a greater size that 8 bytes, since that will unbalance the stack. You can't do a check like sizeof(T) in the method though, because it would fail during the JITing process.
Also, there are some *s next to some of the types up there. There is some extra logic done by the compiler and/or Math.Sqrt when you pass in unsigned numbers vs signed numbers, and how this related to negative numbers. For example:
Console.WriteLine(Math.Sqrt(unchecked((uint)-2))); // 65535.9999847412
Console.WriteLine(helper.Sqrt(unchecked((uint)-2))); // NaN :(
You could improve it and checks above to catch that, though. Also, I don't recommend this solution, especially if you're not comfortable with IL. Plus, this is probably more verbose and complicated than just writing a bunch of different methods to handle the operations you want.
This works, but it's a bit ugly:
public static implicit operator Numeric<T>(double value)
{
return new Numeric<T>((T)Convert.ChangeType(value, typeof(T)));
}
public static implicit operator double(Numeric<T> n)
{
return Convert.ToDouble(n.Value);
}
It will have to be repeated for each supported type, which makes this a lot less generic. I slapped an IConvertible constraint on there for good measure. If anyone has a better solution I'm all ears.
Would anyone be so kind to post the equivalent Java code for a closure like this one (obtained using C#) with anonymous inner classes?
public static Func<int, int> IncrementByN()
{
int n = 0; // n is local to the method
Func<int, int> increment = delegate(int x)
{
n++;
return x + n;
};
return increment;
}
static void Main(string[] args)
{
var v = IncrementByN();
Console.WriteLine(v(5)); // output 6
Console.WriteLine(v(6)); // output 8
}
Furthermore, can anyone explain how partial applications can be obtained if lexical closures are available and viceversa? For this second question, C# would be appreciated but it's your choice.
Thanks so much.
There is no closure yet in Java. Lambda expressions are coming in java 8. However, the only issue with what you're trying to translate is that it has state, which not something that lamba expressions will support i don't think. Keep in mind, it's really just a shorthand so that you can easily implement single method interfaces. You can however still simulate this I believe:
final AtomicInteger n = new AtomicInteger(0);
IncrementByN v = (int x) -> x + n.incrementAndGet();
System.out.println(v.increment(5));
System.out.println(v.increment(6));
I have not tested this code though, it's just meant as an example of what might possibly work in java 8.
Think of the collections api. Let's say they have this interface:
public interface CollectionMapper<S,T> {
public T map(S source);
}
And a method on java.util.Collection:
public interface Collection<K> {
public <T> Collection<T> map(CollectionMapper<K,T> mapper);
}
Now, let's see that without closures:
Collection<Long> mapped = coll.map(new CollectionMapper<Foo,Long>() {
public Long map(Foo foo) {
return foo.getLong();
}
}
Why not just write this:
Collection<Long> mapped = ...;
for (Foo foo : coll) {
mapped.add(foo.getLong());
}
Much more concise right?
Now introduce lambdas:
Collection<Long> mapped = coll.map( (Foo foo) -> foo.getLong() );
See how much nicer the syntax is? And you can chain it too (we'll assume there's an interface to do filtering which which returns boolean values to determine whether to filter out a value or not):
Collection<Long> mappedAndFiltered =
coll.map( (Foo foo) -> foo.getLong() )
.filter( (Long val) -> val.longValue() < 1000L );
This code is equivalent I believe (at least it produces the desired output):
public class Test {
static interface IncrementByN {
int increment(int x);
}
public static void main(String[] args) throws InterruptedException {
IncrementByN v = new IncrementByN() { //anonymous class
int n = 0;
#Override
public int increment(int x) {
n++;
return x + n;
}
};
System.out.println(v.increment(5)); // output 6
System.out.println(v.increment(6)); // output 8
}
}
Assuming we have a generic function interface:
public interface Func<A, B> {
B call A();
}
Then we can write it like this:
public class IncrementByN {
public static Func<Integer, Integer> IncrementByN()
{
final int n_outer = 0; // n is local to the method
Func<Integer, Integer> increment = new Func<Integer, Integer>() {
int n = n_outer; // capture it into a non-final instance variable
// we can really just write int n = 0; here
public Integer call(Integer x) {
n++;
return x + n;
}
};
return increment;
}
public static void main(String[] args) {
Func<Integer, Integer> v = IncrementByN();
System.out.println(v.call(5)); // output 6
System.out.println(v.call(6)); // output 8
}
}
Some notes:
In your program, you capture the variable n by reference from the enclosing scope, and can modify that variable from the closure. In Java, you can only capture final variables (thus capture is only by value).
What I did here is capture the final variable from the outside, and then assign it into a non-final instance variable inside the anonymous class. This allows "passing info" into the closure and at the same time having it be assignable inside the closure. However, this information flow only works "one way" -- changes to n inside the closure is not reflected in the enclosing scope. This is appropriate for this example because that local variable in the method is not used again after being captured by the closure.
If, instead, you want to be able to pass information "both ways", i.e. have the closure also be able to change things in the enclosing scope, and vice versa, you will need to instead capture a mutable data structure, like an array, and then make changes to elements inside that. That is uglier, and is rarer to need to do.
I have the following classes with an implicit cast operator defined:
class A
{
...
}
class B
{
private A m_a;
public B(A a)
{
this.m_a = a;
}
public static implicit operator B(A a)
{
return new B(a);
}
}
Now, I can implicitly cast A to B.
But why can't I implicitly cast A[] to B[] ?
static void Main(string[] args)
{
// compiles
A a = new A();
B b = a;
// doesn't compile
A[] arrA = new A[] {new A(), new A()};
B[] arrB = arrA;
}
Thanks, Malki.
As Mehrdad Afshari mentioned, you're out of luck doing this implicitly. You'll have to get explicit, and it'll involve an array copy. Thankfully, you can probably do it with a one-liner:
arrB = arrA.Cast<B>().ToArray();
Although if you only want to iterate arrB in a foreach statement, you can avoid the copy by omitting ToArray()
Array covariance only works for reference types and in the inheritance hierarchy (note that it's not a representation-changing conversion: just a set of pointers with identical size interpreted differently.) It will not work for value types and user defined conversions.
ConvertAll
Just to be explicit, here is how you use ConvertAll.
In the case where class B has a member of class A called m_a, do this:
B[] arrB;
A[] arrA = Array.ConvertAll(arrB, b => b.m_a);
.
If class B has some member data that you need to manipulate before you can return an object of type A (such as turning a bunch of numerical values into a string description), do this:
class B
{
public static A makeAfromB(B b)
{
// Do something with B data...
A a = new A("data made from B data")
return a;
}
// rest of class B implementation ...
}
// somewhere else in your code...
A[] arrA = Array.ConvertAll(arrB, new Converter<B, A>(B.makeAfromB));
.
You can also use Lambda functions:
A[] arrA = Array.ConvertAll(arrB, new Converter<B, A>(
delegate(B b)
{
// Do something with B data, though object b is const
A a = new A("data made from B data")
return a;
}));
.
It would be nice if ConvertAll could use the implicit operator to do the conversion, but I haven't figured out how to do that.
.
Cast
#Randolpho #bottlenecked
For the cases where you simply want to iterate and would prefer not to make a copy, using cast makes sense. However I have been unable to make it work.
I have an InkPoint class which has a Point object and some other members. I want to call the DrawLines(Pen, Point[]) function. However, I have an array of InkPoint[].
Here is my class and the code I currently have to use, which makes a copy:
public class InkPoint
{
public InkPoint(int x, int y)
{
point = new Point(x, y);
}
public Point point { get; set; }
public static implicit operator Point(InkPoint p)
{
return p.point;
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
InkPoint[] inkPoints = { new InkPoint(1,2), new InkPoint(3,4) };
Point[] points = Array.ConvertAll(inkPoints, x => x.point);
Pen pen = new Pen(Color.Black, 1);
e.Graphics.DrawLines(pen, points);
}
.
I would rather call this, but it won't compile, citing invalid arguments:
e.Graphics.DrawLines(pen, inkPoints.Cast<Point>()); // Compile err: invalid args
.
I've also tried iterating over a cast, but it throws an exception, citing the cast is not valid
foreach (Point p in inkPoints.Cast<Point>()) { } // Exception: cast not valid
.
I don't understand why the specified cast is not valid since I've defined an implicit operator. I'm able to do the following just fine:
InkPoint ip = new InkPoint(10, 20);
Point p1 = ip; // implicit conversion
Point p2 = (Point)ip; // cast
.
For me, the situation is actually slightly more complicated than that. I actually have a list of InkPoints, List<InkPoint>, but the DrawLines function accepts only arrays. So my code looks like this:
List<InkPoint> inkPoints = new List<InkPoint>();
inkPoints.Add(new InkPoint(5, 10));
inkPoints.Add(new InkPoint(10, 15));
Point[] points = inkPoints.ConvertAll<Point>(x => x.point).ToArray();
I can rearrange it slightly to this:
Point[] points = Array.ConvertAll(inkPoints.ToArray(), x => x.point);
.
So I think there's actually two copies happening here. This is annoying since all I want to do is draw the lines. It doesn't seem unreasonable that the DrawLines function should be able to iterate over some array/list that contains references to objects that can be implicitly converted to Point objects.
Imagine for a moment if Arrays used the same syntax as other collections in .Net, and what you're trying to compare is an Array<A> with an Array<B>. You wouldn't compare a List<A> to a List<B>. Well, that's essentially what you're trying.
I'd recommend using a simple extension method to get the result you want, you'll need to change your syntax slightly to say 'B[] arrB = arrA.ToBArray();`
static class ArrayCast {
public static B[] ToBArray(this A[] source) {
var result = new B[source.Length];
for (int i = 0;i < source.Length;i++)
result[i] = source[i];
return result;
}
}