Is it possible to overload operator = in c#?
when i call =, i just want to copy properties, rather than making the left hand reference to refer another instance.
The answer is no:
Note that the assignment operator itself (=) cannot be overloaded. An assignment always performs a simple bit-wise copy of a value into a variable.
And even if it was possible, I wouldn't recommend it. Nobody who reads the code is going to think that there's ANY possibility that the assignment operator's been overloaded. A method to copy the object will be much clearer.
You can't overload the = operator. Furthermore, what you are trying to do would entirely change the operator's semantics, so in other words is a bad idea.
If you want to provide copy semantics, provide a Clone() method.
Why not make a .CopyProperties(ByVal yourObject As YourObject) method in the object?
Are you using a built-in object?
We can Overload = operator but not directly.
using System;
class Over
{
private int a;
public Over(int a )
{
this.a = a;
}
public int A { get => a; }
public static implicit operator int(Over obj)
{
return obj.A;
}
}
class yo
{
public static void Main()
{
Over over = new Over(10);
int a = over;
}
}
Here when you call that operator overloading method , it is calling = operator itself to convert that to int. You cannot directly overload "=" but this way of code means the same.
Related
I have a class in c++ that I'm wrapping into python with pybind11. That class has a std::function, and I'd like to control how the arguments to that function are dealt with (like return value policies). I just can't find the syntax or examples to do this...
class N {
public:
using CallbackType = std::function<void(const OtherClass*)>;
N(CallbackType callback): callback(callback) { }
CallbackType callback;
void doit() {
OtherClass * o = new OtherClass();
callback(o);
}
}
wrapped with
py::class_<OtherClass>(...standard stuff...);
py::class_<N>(m, "N")
.def(py::init<N::CallbackType>(),
py::arg("callback"));
I all works: I can do this in python:
def callback(o):
dosomethingwith(o)
k = N(callback)
, but I'd like to be able to control what happens when callback(o); is called - whether python then will take ownership of the wrapped o variable or not, basically.
I put a printout in the destructor of OtherClass, and as far as I can tell, it never gets called.
OK, I think I figured it out:
Instead of std::function, use a pybind11::function:
using CallbackType = pybind11::function
and then
void doit(const OtherClass &input) {
if (<I want to copy it>) {
callback(pybind11::cast(input, pybind11::return_value_policy::copy));
} else {
callback(pybind11::cast(input, pybind11::return_value_policy::reference));
}
}
I see nothing in pybind11/functional that allows you to change the ownership of the parameters at the point of call, as the struct func_wrapper used is function local, so can not be specialized. You could provide another wrapper yourself, but in the code you can't know whether the callback is a Python function or a bound C++ function (well, technically you can if that bound C++ function is bound by pybind11, but you can't know in general). If the function is C++, then changing Python ownership in the wrapper would be the wrong thing to do, as the temporary proxy may destroy the object even as its payload is stored by the C++ callback.
Do you have control over the implementation of class N? The reason is that by using std::shared_ptr all your ownership problems will automagically evaporate, regardless of whether the callback function is C++ or Python and whether it stores the argument or not. Would work like so, expanding on your example above:
#include <pybind11/pybind11.h>
#include <pybind11/functional.h>
namespace py = pybind11;
class OtherClass {};
class N {
public:
using CallbackType = std::function<void(const std::shared_ptr<OtherClass>&)>;
N(CallbackType callback): callback(callback) { }
CallbackType callback;
void doit() {
auto o = std::make_shared<OtherClass>();
callback(o);
}
};
PYBIND11_MODULE(example, m) {
py::class_<OtherClass, std::shared_ptr<OtherClass>>(m, "OtherClass");
py::class_<N>(m, "N")
.def(py::init<N::CallbackType>(), py::arg("callback"))
.def("doit", &N::doit);
}
I have this eror:
The '.' operator cannot be applied to operand of type 'method group'
(CS0023)
I know that there is a question like this, but I checked it and the problem with that was put System before the method.
I have this code
private int posCuriosidad = 0;
// Use this for initialization
void Start () {
Random();
}
public void Random(){
posCuriosidad = Random.Range(0,9);
}
but I don't know why I get the error.
That's because calling Random.X inside a method named Random will be mapped to try to invoke X on the method group of your method.
You clearly wanted to use the built-in Random type, not your own method.
Here's a couple of ways to do this:
Rename your method, "Random" is not a verb, "Randomize" is though but you should strive to make the purpose of the method clear through its name, so perhaps "RandomizePosition" would be better?
public void RandomizePosition()
{
posCuriosidad = Random.Range(0,9);
}
Explicitly refer to the built-in Random type:
UnityEngine.Random.Range(0,9);
Say I am creating a Dictionary class in typescript. Is there a way to have operator overrides so I can define the operator "[string]" instead of having to use the function get(string)?
No, you cannot have operator overloading. JavaScript does not have a notion of this.
You can override toString, though:
class Thing {
toString() {
return 'I am a Thing!';
}
}
var x = new Thing();
console.log('X says ' + x); // Prints "X says I am a Thing!"
I've got an object, which I'll call MyObject. It's a class that controls a particular data row.
I've then got a collection class, called MyObjectCollection:
public class MyObjectCollection : List<MyObject> {}
Why can I not do the following:
List<MyObject> list = this.DoSomethingHere();
MyObjectCollection collection = (MyObjectCollection)list;
Thanks in advance.
Edit: The error is InvalidCastException
My guess is that DoSomethingHere doesn't return an instance of MyObjectCollection.
Let's get rid of all the generics etc here, as they're not relevant. Here's what I suspect you're trying to do:
public static object CreateAnObject()
{
return new object();
}
object o = CreateAnObject();
string s = (string) o;
That will fail (at execution time) and quite rightly so.
To bring it back to your code, unless DoSomethingHere actually returns a MyObjectCollection at execution time, the cast will fail.
Because a List<MyObject> is not a MyObjectCollection. The reverse is true: you could cast a MyObjectCollection to a List because MyObjectCollection inherits from List<MyObject> and thus, for all intents and purposes, IS A List<MyObject>.
The only thing you can do is to define a constructor on MyObjectCollection that takes an Ienumerable as a parameter and initalizes itself with the data in the other one, but that will make a new object containing the same data:
public class MyObjectCollection : List<MyObject>
{
public MyObjectCollection(IEnumerable<MyObject> items)
{
Addrange(items);
}
}
UPDATE:
As noted in the comment, you COULD have the cast succeed at runtime, provided that DoSomething actually returns an instance of MyObjectCollection. If it does, the object effectively is a MyObjectCollection, and the cast is completely legal.
I'd have to say, it is bad practice in my view to upcast something like that. If the function returns a List, you should not rely on a specific implementation of List. Either modify the return type of DoSomething, if you own that function, and return a MyObjectCollection, or deal with it as a list.
Without knowing what exactly is created inside DoSomething() we have to assume either:
You have a misunderstanding about the inheritence in .Net.
you have
A : B
B DoSomething()
{
return new B();
}
// then this is
B b = new B();
A a = (A)b;
Clearly b is a B but not an A. B might look much like A but it is not (if you traverse the parentage of b you won't find A anywhere)
This is true irrespective of the Generics involved (though that sometimes can cause situations where something that could work doesn't see the co-contra variance in c# 4.0)
or
A : B
B DoSomething()
{
return new A();
}
// then this is
B b = new A();
A a = (A)b;
Which in the absence of Generics will work.
You can't do it because (I guessing) the list instance returned from DoSomethingHere isn't derived from MyObjectCollection
You could create an implicit operator that would allow you to convert between your object and the list. You would need an constructor that takes a list and to property that returns the underlaying list.
public static implicit operator List<MyObject>(MyObjectCollection oCollection)
{
//Convert here
return MyObjectCollection.BaseList;
}
public static implicit operator MyObjectCollection(List<MyObject> oList)
{
//Convert here
return new MyObjectCollection(oList);
}
One advantage of lambda expressions is that you have to evaluate a function only when you need its result.
In the following (simple) example, the text function is only evaluated when a writer is present:
public static void PrintLine(Func<string> text, TextWriter writer)
{
if (writer != null)
{
writer.WriteLine(text());
}
}
Unfortunately, this makes using the code a little bit ugly. You cannot call it with a constant or variable like
PrintLine("Some text", Console.Out);
and have to call it this way:
PrintLine(() => "Some text", Console.Out);
The compiler is not able to "infer" a parameterless function from the passed constant. Are there any plans to improve this in future versions of C# or am I missing something?
UPDATE:
I just found a dirty hack myself:
public class F<T>
{
private readonly T value;
private readonly Func<T> func;
public F(T value) { this.value = value; }
public F(Func<T> func) {this.func = func; }
public static implicit operator F<T>(T value)
{
return new F<T>(value);
}
public static implicit operator F<T>(Func<T> func)
{
return new F<T>(func);
}
public T Eval()
{
return this.func != null ? this.func() : this.value;
}
}
Now i can just define the function as:
public static void PrintLine(F<string> text, TextWriter writer)
{
if (writer != null)
{
writer.WriteLine(text.Eval());
}
}
and call it both with a function or a value.
I doubt that C# will get this feature, but D has it. What you've outlined is a suitable way to implement lazy argument evaluation in C#, and probably compiles very similarly to lazy in D, and in more pure functional languages.
All things considered, the four extra characters, plus optional white space, are not an exceptionally large price to pay for clear overload resolution and expressiveness in what is becoming a multi-paradigm strong-typed language.
The compiler is very good at inferring types, it is not good at inferring intent. One of the tricky things about all the new syntactic sugar in C# 3 is that they can lead to confusion as to what exactly the compiler does with them.
Consider your example:
() => "SomeText"
The compiler sees this and understands that you intend to create an anonymous function that takes no parameters and returns a type of System.String. This is all inferred from the lambda expression you gave it. In reality your lambda gets compiled to this:
delegate {
return "SomeText";
};
and it is a delegate to this anonymous function that you are sending to PrintLine for execution.
It has always been important in the past but now with LINQ, lambdas, iterator blocks, automatically implemented properties, among other things it is of the utmost importance to use a tool like .NET Reflector to take a look at your code after it is compiled to see what really makes those features work.
Unfortunately, the ugly syntax is all you have in C#.
The "dirty hack" from the update does not work, because it does not delay the evaluation of string parameters: they get evaluated before being passed to operator F<T>(T value).
Compare PrintLine(() => string.Join(", ", names), myWriter) to PrintLine(string.Join(", ", names), myWriter) In the first case, the strings are joined only if they are printed; in the second case, the strings are joined no matter what: only the printing is conditional. In other words, the evaluation is not lazy at all.
Well those two statements are completely different. One is defining a function, while the other is a statement. Confusing the syntax would be much trickier.
() => "SomeText" //this is a function
"SomeText" //this is a string
You could use an overload:-
public static void PrintLine(string text, TextWriter writer)
{
PrintLine(() => text, writer);
}
You could write an extension method on String to glue it in. You should be able to write "Some text".PrintLine(Console.Out); and have it do the work for you.
Oddly enough, I did some playing with lazy evaluation of lambda expressions a few weeks back and blogged about it here.
To be honest I don't fully understand your problem, but your solutions seems a tad complicated to me.
I think a problem I solved using lambda call is similar, maybe you could use it as inspiration: I want to see if a key exists in a dictionary, if not, I would need to execute a (costly) load operation.
public static class DictionaryHelper
{
public static TValue GetValueOrLambdaDefault<TKey, TValue> (this IDictionary<TKey, TValue> dictionary, TKey key, Func<TValue> func)
{
if (dictionary.ContainsKey(key))
return dictionary[key];
else
return func.Invoke();
}
}
[TestClass]
public class DictionaryHelperTest
{
[TestMethod]
public void GetValueOrLambdaDefaultTest()
{
var dict = new Dictionary<int, string>();
try
{
var res1 = dict.GetValueOrLambdaDefault(1, () => LoadObject());
Assert.Fail("Exception should be thrown");
}
catch { /*Exception should be thrown*/ }
dict.Add(1, "");
try
{
var res1 = dict.GetValueOrLambdaDefault(1, () => LoadObject());
}
catch { Assert.Fail("Exception should not be thrown"); }
}
public static string LoadObject()
{
throw new Exception();
}
}