In the last line of Main(), I get an error for trying to do pointer stuff, but what I'm actually trying to do is invoke the multiplication operator I defined inside the Foo class. If that isn't the syntax for invoking the multiplication, what is?
namespace test
{
class Program
{
class Foo
{
int foo;
public Foo(int n)
{
foo = n;
}
public static object operator *(Foo a,Foo b)
{
return new Foo(a.foo * b.foo);
}
}
static void Main(string[] args)
{
Foo a = new Foo(2);
Foo b = new Foo(3);
a * b;
}
}
}
I'm sure it's something stupid, but I don't see it.
In C#, the only expressions that can be used as statements (i.e. expressions which you can evaluate and simply ignore the result of the evaluation) are:
assignments: a = b;
the most obvious valid statement, but even the assignment expression has a result value, which means you can write one-liners like if ((a = b) == c) doStuff(); - so you are still "not using" the result of the assignment expression when doing a plain assignment
method calls: doStuff();
even if doStuff returns a value, you can use it as a statement
if you call a.ToString(); without storing the string anywhere, compiler won't complain
increments/decrements: i++;, i--;
post/pre-increment result semantics are pretty much the same in all C-like languages, it doesn't matter if you use the result (as in var x = i++;) or not
awaiting on a method: await doAsyncStuff();
you can await on an async operation without having to consume the result (this is basically analogous to plain method calls)
new object expressions: new Foo();
even if you don't assign the newly instantiated object to anything, its constructor might do a number of things affecting the state of the program, as well as create static references to itself (otherwise it will just get collected)
So, since are not consuming the result of this operation (assigning it to a variable), C# compiler assumes you are trying to define a variable b of type a*:
static void Main(string[] args)
{
Foo a = new Foo(2);
Foo b = new Foo(3);
// this is seen by the compiler as "type* variable;"
a * b;
}
This is why it gives you several compiler errors, like:
a is a variable, but is being used as a type
pointers are only allowed in an unsafe context
If you used a + operator, it wouldn't have mentioned any pointers, it would have just complained that you weren't supposed to use the expression as a statement, so it would probably make it more obvious.
To resolve the error, assign the result of the expression to a variable:
// type of `result` is an object, btw
var result = a * b;
As a side note, it would be wiser that your operator * method returns a result of type Foo, instead of a plain object:
public static Foo operator *(Foo a, Foo b)
{
...
}
// type of `result` is now `Foo`, as it should be
Foo result = a * b;
Final suggestion would be that this concrete example is a good candidate for an immutable struct, instead of a class (similar to the Point struct, for example).
Related
I have a converter method:
MyPoco Convert(dynamic p) => new MyPoco { A = p.X, B = p.Y };
void Test()
{
dynamic item = new { X = 1, Y = 2 };
var poco = (MyPoco)Convert(item);
}
I have to explictly cast the result to MyPoco, otherwise poco will become a dynamic variable, too.
But, if I inline the Convert method;
void Test()
{
MyPoco Convert(dynamic p) => new MyPoco { A = p.X, B = p.Y };
dynamic item = new { X = 1, Y = 2 };
var poco = Convert(item);
}
I don't need to cast ConvertItem to MyPoco. Is there a reason for this behavior? It should be easy for the compiler to know that Convert return-type is MyPoco, right?
There is a difference between them which could be the reason - local functions don't support overloading. I think it is important - imagine we have two methods with the same name and with different input and output types
static void Main(string[] args)
{
dynamic d = null;
var result = Hello(d);
Console.WriteLine("Hello World!");
}
static string Hello(string s)
{
return s;
}
static int Hello(int i)
{
return i;
}
It means the result may be string or int - we don't know it in compile time.
While for the following code we get the error that local variable or function already declared
static void Main(string[] args)
{
string Hello(string s)
{
return s;
}
int Hello(int s) // error - local variable or function with the same name already declared
{
return s;
}
dynamic d = null;
var result = Hello(d);
Console.WriteLine("Hello World!");
}
We can only write something like this
static void Main(string[] args)
{
string Hello(string s)
{
return s;
}
dynamic d = null;
var result = Hello(d);
Console.WriteLine("Hello World!");
}
So when compiler sees the local Hello(...) call it knows that return type is string.
Upd:
Regarding the compiler ability to infer correct type in case of dynamic.
I think yes, it is possible for compiler to catch such cases - if we know in compile time that there is the only one method,
there is no chance that in runtime another one will appear.
I could imagine e.g. the method we call is in another assembly, and in runtime we loaded newer version which has different signature - with dynamic it will work, but for the, say, private static method with no overloads I think we could infer non-dynamic type.
But I think, it is was decided to implement it that way for the sake of simplicity - it is easier to keep in mind simple rule - everything that touches dynamic - dynamic.
For local functions for simplicity I think it would be easier to also have them dynamic. I think it is just decision made by different people implementing that.
I checked the roslyn source code trying to find information about that.
The place where it is defined is Binder_Invocation.cs, BindMethodGroupInvocation method.
For local function the following method is called
private BoundExpression BindLocalFunctionInvocationWithDynamicArgument(
SyntaxNode syntax,
SyntaxNode expression,
string methodName,
BoundMethodGroup boundMethodGroup,
DiagnosticBag diagnostics,
CSharpSyntaxNode queryClause,
MethodGroupResolution resolution)
{
// Invocations of local functions with dynamic arguments don't need
// to be dispatched as dynamic invocations since they cannot be
// overloaded. Instead, we'll just emit a standard call with
// dynamic implicit conversions for any dynamic arguments. There
// are two exceptions: "params", and unconstructed generics. While
// implementing those cases with dynamic invocations is possible,
// we have decided the implementation complexity is not worth it.
// Refer to the comments below for the exact semantics.
As you can see the also say about overloading, but for the normal method call no any information about the reason
else
{
if (HasApplicableConditionalMethod(resolution.OverloadResolutionResult))
{
// warning CS1974: The dynamically dispatched call to method 'Goo' may fail at runtime
// because one or more applicable overloads are conditional methods
Error(diagnostics, ErrorCode.WRN_DynamicDispatchToConditionalMethod, syntax, methodGroup.Name);
}
// Note that the runtime binder may consider candidates that haven't passed compile-time final validation
// and an ambiguity error may be reported. Also additional checks are performed in runtime final validation
// that are not performed at compile-time.
// Only if the set of final applicable candidates is empty we know for sure the call will fail at runtime.
var finalApplicableCandidates = GetCandidatesPassingFinalValidation(syntax, resolution.OverloadResolutionResult,
methodGroup.ReceiverOpt,
methodGroup.TypeArgumentsOpt,
diagnostics);
if (finalApplicableCandidates.Length > 0)
{
result = BindDynamicInvocation(syntax, methodGroup, resolution.AnalyzedArguments, finalApplicableCandidates, diagnostics, queryClause);
}
else
{
result = CreateBadCall(syntax, methodGroup, methodGroup.ResultKind, analyzedArguments);
}
They create dynamic if there is at least one canditate.
So, as I said, I think it could be done non-dynamic, but the people who implemented it originally kept it dynamic, probably for simplicity.
What you could do in order to find more details is to try to implement the case when no overloading methods, changing the code
if (finalApplicableCandidates.Length > 0)
{
result = BindDynamicInvocation(syntax, methodGroup, resolution.AnalyzedArguments, finalApplicableCandidates, diagnostics, queryClause);
}
by adding the check if Length == 1 then call BindInvocationExpressionContinued instead of BindDynamicInvocation
and run the tests and check if something fails, maybe it helps.(I didn't even manage to get the roslyn project built, dotnet core is a bit weird)
P.S.
According to this
if (boundMethodGroup.TypeArgumentsOpt.IsDefaultOrEmpty && localFunction.IsGenericMethod)
{
Error(diagnostics, ErrorCode.ERR_DynamicLocalFunctionTypeParameter, syntax, localFunction.Name);
return BindDynamicInvocation(
For local function we could get dynamic instead of concrete type.
If you type something like this
static void Main(string[] args)
{
int TestFunc<T>(T data)
{
return 1;
}
dynamic d = 2;
var r = TestFunc(d);
}
Yes, it will give the error, but if you check the inferred type it of r will show dynamic))
I have a class named FloatPlugIn. I want user to be able to do things like
FloatPlugIn x = new FloatPlugIn();
x.Minimum = -100;
x.Maximum = 100;
float y = 123;
x = y;
That is why I decided to add implicit operator to my class
public static implicit operator FloatPlugIn(float p)
{
return new FloatPlugIn() { Default = p };
}
Problem is that implicit operator has to be static that is why during conversion new instance of my class is created. As a result I am loosing all the information that was located inside of "old" instance.
Is there a way to fix that? I want float value to be applied to existing instance, not to completely replace it.
I don't think you're understanding what conversion does - it's not casting - it must create a new instance. It only makes sense to make it non-static if it were only updating the existing instance.
I think it's better in this case if you either use x.Default = y; or if you create a constructor that takes the float like this:
// Constructor
public FloatPlugIn(float p)
{
Default = p;
}
Usage:
float y = 123;
FloatPlugIn x = new FloatPlugIn(y);
The semantics of the assignment operator requires that behavior. In fact:
The assignment operator (=) stores the value of its right-hand operand in the storage location, property, or indexer denoted by its left-hand operand and returns the value as its result. The operands must be of the same type (or the right-hand operand must be implicitly convertible to the type of the left-hand operand).
It is not the purpose of the implicit conversion operator to modify a destination value—note that there may not be any such destination value, such as in case you pass the value to a parameter of a method.
I want float value to be added to existing instance, not to completely replace it.
If you want an addition (in whatever specific sense that would mean in your case), consider overriding the addition + operator, which in turn has effect on the addition assignment += operator. However, you won't eliminate the creation of a new FloatPlugIn instance anyway.
Consider you'd have the following method in FloatPlugIn, which would modify an existing instance:
public void Add(float f)
{
// do whatever 'addition' means in your case
}
Then the + operator should work like this:
public static FloatPlugIn operator +(FloatPlugIn a, float b)
{
FloatPlugIn result = a.Clone(); // here Clone() denotes any custom method that creates a copy of that instance
result.Add(b);
return b;
}
In your code, the following would work then:
FloatPlugIn x = new FloatPlugIn();
x.Minimum = -100;
x.Maximum = 100;
float y = 123;
x += y; // a new instance is created, but the 'addition' logic is preserved
Also, the same will intuitively work in case of passing a value to a method call:
ProcessMyFloatPlugin(x + 123.0f);
You can see that it is a really good idea to create a new instance of FloatPlugIn as a result of an operator. Otherwise, an in-place modification of x would be, in fact, a nasty side-effect, completely unexpected by any other developer. Note that if performance (avoiding dynamic memory allocations) is a concern, consider using structs.
When I call a function and replace one of the parameters with dynamic, the compiler inferres the function result to be dynamic. I don't understand why this happens.
Example: the inferred type for a is dynamic, so this code compiles, but of course fails at runtime with RuntimeBinderException:
dynamic b = "";
var a = MethodWithoutOverloads("", b);
a.DoesNotExist();
...
public string MethodWithoutOverloads(string a, string b) { ... }
Somebody knows why the type inferred is not the return type of the function?
EDIT: edited to make clear this happens with methods without overloads
You are right in the sense that the compiler could reason out that all String.Format overloads return a string and therefore infer that a must be a string no matter what b really is.
The truth is that the compiler does not do that. It solves the general case, which is good, and because overloads with different return types are valid in C#, it simply assigns the return type as dynamic and lets the runtime figure it out.
Answering your specific question,
public string MethodWithoutOverloads(string a, string b) { ... }
dynamic a = "";
var result = MethodWithoutOverloads(a, a); // result is dynamic.
Lets imagine the compiler decides that result is string and you publish to the wild west your library. Then, later on, you decide to add an overload with the following signature:
public int MethodWithoutOverloads(int a, int b) { ... }
Now, what should the type of result be? And, what happens to existing code that relied on result being strongly typed to string?
string result = MethodWithoutOverloads(someDynamicVariable, someOtherDynamicVariable);
The semantics change completely; before a consumer had a safe strongly typed variable, now he suddenly has a potentially unsafe implicit cast that can blow up in runtime.
Because the compiler doesn't know which method is going to be invoked at run time.
For example, you may have the two methods:
int MyMethod(int a)
{
return 5;
}
double MyMethod(string a)
{
return 6.0;
}
And you write the following code:
dynamic myThing = 5;
var myResult = MyMethod(myThing);
Considering we've explicitly said myThing is dynamic, and this its type is to be determined at runtime, we have no idea which method will be invoked (if any). Thus, we don't know the return type, either.
This C++ code checks if o is a Node * and if so, calls a method on d.
if (Node * d = dynamic_cast<Node *>(o)) d->do_it();
What's the shortest and/or most efficient way to write the equivalent in C#?
Assuming that Node is a class then do the following
Node d = o as Node;
if (d != null) {
d.do_it();
}
If instead it's a struct then try this
if (o is Node) {
((Node)o).do_it();
}
As of C# 6 (July 2015), assuming Node is a class (or Nullable<T>, string, etc), using your example where you
check if o is a Node (not actually the same as converting o to a Node--see note about casting vs converting below)
if so, call do_it()
immediately discard the cast value
you can use the null-conditional operator:
(o as Node)?.do_it();
This syntax also handles the case where o is, in fact, declared as Node, but happens to be null.
If you want to keep the cast variable, as of C# 7 (March 2017), you can run:
if (o is Node node)
{
node.do_it();
}
The variable node at this point is in the scope outside of the if statement, equivalent to:
Node node = o as Node;
if (node != null)
{
node.do_it();
}
So, if you want to only continue the execution if o is a Node, you can write:
if (!(o is Node node))
{
return; // or continue, etc
}
node.do_it();
// ...
Note: The is keyword will always return false if o is null, even if you directly specify the type and then ask if that variable is that type.
string foo = null;
if (foo is string)
{
// never gets here
Console.WriteLine(foo);
}
Casting vs Converting
The is and as keywords do the same as C++'s dynamic_cast<T>: they will check against the specified type, subtype, or interface, but will not actually change the value in memory. They simply tell the compiler which methods should be available on the variable.
There's a misnomer amongst C# users where we use the words "cast" and "convert" interchangeably. This likely stems from the fact that we often know that a base type variable is always going to be a subtype, and so we use the convert syntax when puritanically we should be using the cast syntax:
void Foo(MyBaseType value)
{
// let's assume `value` will always be a MySubType
MySubType subTypeValue = (MySubType)value;
}
This syntax will throw at runtime if value is not, in fact, MySubType.
Converting differs from casting in that the value in memory may change. Consider int and double.
void Foo()
{
// implicit converting
int x = 1;
double y = x;
// explicit converting
y = 1.5;
x = (int)y;
}
In each of these cases, the literal value stored in memory changes format. ints can always be represented by a double--there will never be a loss in data--and so there is a defined implicit operator that will manipulate the data in memory into the new format. doubles, being floating point values and having a range larger than ints, cannot guarantee no loss in data, so C# requires an explicit conversion (usually termed "explicit cast") via the explicit operator to indicate to the compiler that we're okay with losing data.
With classes, we can define our own implicit and explicit operators which will manipulate the data whatever way we see fit. This is where the misnomer between convert and cast gets messy.
using System;
public class Program
{
public static void Main()
{
Foo foo = new Foo();
Bar bar = (Bar)foo;
// writes "1" (or would, if the program compiled)
Console.WriteLine(bar);
// throws compilation error: "Cannot convert type `Foo' to `Bar' via built-in conversion"
bar = foo as Bar;
// note: the same would happen if `foo` was type int? and `bar` was type `double?`
// even though double? can be converted to int?
}
}
class Foo
{
public readonly int Value = 1;
public static explicit operator Bar(Foo foo)
{
return new Bar(foo.Value.ToString());
}
}
class Bar
{
public readonly string Value;
public Bar(string value)
{
Value = value;
}
}
The as operator returns null if o is not a Node:
Node d = o as Node;
if (d != null)
{
d.do_it();
}
You can use the is keyword in C#.
if (o is Node)
{
}
I have a method which is taking in a parameter that is a Interface object
like this
private void SomeMethod(InterfaceA IUA)
Inside the method I have a statement like this
ClassD someVar = (ClassD)(((ClassC)((ClassB)IUA)).D);
everything if fine and dandy. However, in certain cases the object IUA might be instance of ClassZ rather than ClassB. So in that case the above line errors out. Is there a way to find out, before doing above statement, that which class does the object really belong to? If i know that before hand then I can have an If statement and do the following
ClassZ someVar = (ClassD)(((ClassC)((ClassZ)IUA)).Z);
I come from java background...In java i know we have getClass() ...what would be the equivalent in .net?
You really shouldn't be writing code like this without good reason.
That said: you can use is
if (a is ClassB)
{
ClassB b = (ClassB)a;
}
else if (a is ClassZ)
{
ClassZ z = (ClassZ)a;
}
...or as:
ClassB b = a as ClassB;
if (b != null)
{
// ...
}
Well, for starters, you're not really supposed to downcast from interface to a class, unless you have a really good reason to do so. If you need ClassD functionality, then your method should receive ClassD, not InterfaceA.
Another thing that confuses me is the multiple downcasting. I use both Java and C# and I've never seen the need to do a multiple cast like that.
Finally, you could use operator "is" to find out whether certain type inherits from a certain class or implements a certain interface, as in
if (IUA is ClassD)
{
// do something
}
You can do
if (someVar is ClassZ)
Which returns TRUE if someVar is-a ClassZ,
or
someVar.GetType ()
to get the actual class
How about
if(IUA is ClassB)
someVar = (IUA as ClassB).B;
elseif (IUA is ClassZ)
someVar = (IUA as ClassZ).Z;
That should work, though you get the mandatory scolding that this is a rather poor architecture.
What is the point of passing the interface if your just going to cast it away? You might want to re-evaluate the design as code like this defeats the purpose of polymorphism.
Also you should not use 'is' to test the type. Since you are going to cast the object anyway you should use 'as' and test for null.
Okay, a few different options here:
The equivalent for Java's getClass() is GetType(); you can use typeof(...) to retrieve the Type object for a type you know at compile-time. This isn't the best way of testing things though, unless you're interested in exact equality.
The equivalent of Java's instanceof operator is the is operator in C#:
if (x is SomeType) ...
This can be used with boxed values to check for value types, too:
if (x is int) ...
A related operator is the as operator, which doesn't return true or false, but a reference of the type specified. The type has to be a nullable type (reference or nullable value type) and the result is the original value but strongly typed as the target type if the value is a reference of an appropriate type, or null otherwise. For instance:
object x = "hello";
string y = x as string; // y = "hello" now
Stream z = x as Stream; // z = null now
In the case where you want to check whether or not a reference is of a particular type, and then use it as a reference of that type, a common pattern is:
object x = GetObjectFromSomewhere();
string y = x as string;
if (y != null)
{
Console.WriteLine(y.Length); // Whatever
}
This is more efficient than the equivalent to what's required in Java:
object x = GetObjectFromSomewhere();
if (x is string)
{
string y = (string) x;
Console.WriteLine(y.Length); // Whatever
}
If it's a bug for the reference to be of the wrong type, just cast - that way you'll get an exception thrown if you've got a bug, which is almost certainly the best course of action at that point.
I don't think it's necessary to cast IUA to ClassB. You're not using any of the ClassB methods as far as I can tell.
You could do something like
If (IUA is ClassB)
//I am class b
However, given that your method is taking an interface, I would question your design if you are looking to get back to the actual concrete type. Can you re-factor to create an interface method that you can use to perform the actions of that method.
From MSDN:
public static void Test (object o)
{
Class1 a;
Class2 b;
if (o is Class1)
{
Console.WriteLine ("o is Class1");
a = (Class1)o;
// do something with a
}
else if (o is Class2)
{
Console.WriteLine ("o is Class2");
b = (Class2)o;
// do something with b
}
else
{
Console.WriteLine ("o is neither Class1 nor Class2.");
}
}
You should use method overloading, this is how it should look:
private void SomeMethod(ClassB obj) {
DoMoreStuff(obj.B);
}
private void SomeMethod(ClassZ obj) {
DoMoreStuff(obj.Z);
}
private void DoMoreStuff(int val) {
// ..
}