I have a C# script that requires an item to be added or removed from a list. I thought it would be nicer to use += and -= operators.
In C# an operator is done by:
public Foo operator +(Foo A, Foo B){
//Some adding code;
return C;
}
however I only get a syntax error when I attempt:
public SpriteValues operator +=(SpriteValues A){
//Add A to this
return this;
}
I know in python it would be done using:
def __iadd__(self, A):
#Add A to this
return self
So how do I do this in C#?
From here you can't overload += directly but note the comment:
Assignment operators cannot be overloaded, but +=, for example, is evaluated using +, which can be overloaded
So if you only overload the + operator that should be fine
You can't overload the += operator as a += b it is just shorthand for a = a + b.
Overloading the + operator will allow you to use += on your object.
You can't overload +=, but it utilizes the + operator with the assignment, so as long as you override + it should work.
I'd advocate not implementing +/- for these operations. In many cases it will result in confusing usage. Assuming your list is mutable (that's why you want add and remove operations), defining +/- becomes tricky. There are several issues to think about.
One requirement is that + should not cause side effects. It would be very weird if var z = x + y mutated x or y. Therefore, you must create new list inside +/-. Most developers would not expect this to happen and it is going to be very expensive to copy the items every time one is added.
Let's say you can live with copying on every add/remove. What would you expect the state of the program to be after executing this fragment:
var list1 = new MyList();
var list2 = list1;
list2 += item;
Most would expect that list1 and list2 to refer to the same list object that now has item in it. However, since + creates a new list, that is not what happens. list1 is empty and list2 is a different list that contains item. This is very weird.
You either have to drop the requirement that the list is mutable, +/- won't cause side effects, or the expectation that += won't create a new list. Of course, in the framework delegates have these operators and they are immutable. The behavior of +/- for delegates is one of the more confusing parts of the language so I would not advocate that you emulate it.
I would go the normal route of implementing Add/Remove methods who semantics are well-known and can be easily predicted.
Lists are very common, generic classes, and as such have well-known methods by which things can be added to or removed from them (namely Add and Remove).
If you go overloading operators instead you'll just confuse the heck out of the poor guy that will come along and have to maintain your code once you're gone.
Related
SonarQube identifies a bug in my code based on rule csharpsquid:S2114 and I cannot see how this applies to the code. The code in question concatenates the values IEnumerable from a dictionary Dictionary<string,object> attributes one time after another like so:
var valuesTwice = attributes.Values.Concat(attributes.Values).ToArray();
The rule states:
Collections should not be passed as arguments to their own methods
Passing a collection as an argument to the collection's own method is either an error - some other argument was intended - or simply nonsensical code.
Further, because some methods require that the argument remain unmodified during the execution, passing a collection to itself can result in an unexpected behavior.
However, as I understand it, this is not actually a method on the list attributes.Values itself, but an extension method, so the code in question could be written (less elegantly, in my opinion) like the variant added below (the original included for comparison):
var valuesTwice = attributes.Values.Concat(attributes.Values).ToArray();
var valuesTwice = Enumerable.Concat(attributes.Values, attributes.Values).ToArray();
From reading the documentation page on Concat, I don't see how the statement can have any unintended effects on the attributes Dictionary, which is what I understand the rule is to guard against. It is not like the Concat modifies the Values structure in the Dictionary.
My only explanation is that SonarQube's matching rules confuse this extension method as a method on the actual collection itself. Is this Concat safe to do, and I can just ignore this application of the rule, or am I missing something?
As a bonus question: Is there an alternative (elegant) way to achieve the same effect, producing an array where the Values are repeated?
Update/Clarification: My problem with the SonarQube description is the lack of distinction between passing a collection to a method on the collection itself (which may have unintended side effects that I think the rule is about) and passing a collection as both arguments to an extension method, see stackoverflow.com/questions/100196/net-listt-concat-vs-addrange. My reasoning is that the Concat method does not alter the collection, but returns a new collection (or rather, enumerable) combining the two passed collections. I question if Enumerable.Concat is an appropriate match for the rule, where I would agree that AddRange method is: feeding a collection "with its own tail" by passing it to AddRange, I would have a problem with, since it modifies the collection.
The reasoning behind the check in SonarQube can be found in their JIRA (and C# version, and JIC github PR). And it makes sense in quite a lot of scenarios.
As for bonus question, it is matter of preference and, maybe performance(if the code will be called a lot), but you can try something like:
var x = new[] {1,2};
var times = 2;
x.SelectMany(i => Enumerable.Repeat(i, times)).ToList();
It will produce not the same output though, your code will return [1, 2, 1, 2] and this will - [1, 1, 2, 2].
You can also create your own extension method:
public static IEnumerable<T> RepeatElements<T>(this IEnumerable<T> en, int times)
{
// check arguments
var inner = en is ICollection<T> col ? col : en.ToList();
foreach (var elem in inner)
{
for (int i = 0; i < times; i++)
{
yield return elem;
}
}
}
Reorder cycles if return order of elements is important.
In my project I have a MyClass which implements IMyClass. I need to return a list of IMyClass by transforming a list of other items. For simplicity's sake, assume that I can create a MyClass just by passing another item into its constructor, i.e. new MyClass(item).
Consider the following two lines, which (as far as I know) produce the same result:
var option1 = items.Select(item => new MyClass(item)).Cast<IMyClass>().ToList()
var option2 = items.Select(item => new MyClass(item) as IMyClass).ToList()
It seems to me that option #1 would require a double enumeration, once to cast all the items to my interface and once to generate the list. If I'm right then option #2 would be smarter. However, I've never seen any code using something like option #2, and I tend to assume that I'm not smart enough to come up with something clever that the rest of the C# community did not.
On a side note, I think option #2 is more aesthetically pleasing, but that's just me.
My question is: is my option #2 a better idea like I think it is? Are there are any gotchas I'm missing or other reasons why I'd want to stick with option #1? Or am I perhaps comparing two stupid ideas when there is a smarter third one that I'm missing completely?
I'd go for option 3:
var option3 = items.Select<Foo, IMyClass>(item => new MyClass(item))
.ToList()
Alternatively, don't use as but just cast normally:
var option4 = items.Select(item => (IMyClass) new MyClass(item))
.ToList()
Both of these seem cleaner than using Cast.
Oh, and as of C# 4 with .NET 4 (due to covariance), you could put a type argument on the ToList call instead:
var option5 = items.Select(item => new MyClass(item))
.ToList<IMyClass>()
It seems to me that option #1 would require a double enumeration
This is not true. In both cases, the items collection is only enumerated when you get to ToList().
The line
var option1 = items.Select(item => new MyClass(item)).Cast<IMyClass>().ToList()
is equivalent to
var option1 = items.Select(item => new MyClass(item)).Select(x => (IMyClass)x).ToList()
The only difference between the two is that the first one requires two function calls per item (unless C# inlines the lambdas somehow, which I don't believe is the case) while the second option requires only one.
Personally, I'd go with the second one as a matter of style.
Which one you use is a matter of preference, something we really cannot answer for you.
But your intuition if sort-of correct that Cast adds a second layer of iteration to your loop. It's very minor, and I doubt it will produce any measurable difference in performance, but the Cast method returns a new IEnumerable object that basically does this:
foreach (object obj in source) yield return (TResult)obj;
The effect is mostly another level on the call stack; since it uses yield it will only iterate on demand, like most other IEnumerable methods. But it will have to return though two levels of iterator state instead of one. Whether that matters for you is something you'll need to measure for your own applications.
(Also note that, at least according to the reference source, it does an unsafe cast, which might throw an exception if the cast is invalid. That's another reason to prefer your option #2.)
You can always provide explicit type arguments to your Select
var option2 = items.Select<IItem,IMyClass>(item => new MyClass(item)).ToList();
where IItem is a type or interface to which items could be cast.
I have an implementation of DynamicDictionary where all of the entries in the dictionary are of a known type:
public class FooClass
{
public void SomeMethod()
{
}
}
dynamic dictionary = new DynamicDictionary<FooClass>();
dictionary.foo = new FooClass();
dictionary.foo2 = new FooClass();
dictionary.foo3 = DateTime.Now; <--throws exception since DateTime is not FooClass
What I'd like is to be able to have Visual Studio Intellisense work when referencing a method of one of the dictionary entries:
dictionary.foo.SomeMethod() <--would like SomeMethod to pop up in intellisense
The only way I've found to do this is:
((FooClass)dictionary.foo).SomeMethod()
Can anyone recommend a more elegant syntax? I'm comfortable writing a custom implementation of DynamicDictionary with IDynamicMetaObjectProvider.
UPDATE:
Some have asked why dynamics and what my specific problem is. I have a system that lets me do something like this:
UI.Map<Foo>().Action<int, object>(x => x.SomeMethodWithParameters).Validate((parameters) =>
{
//do some method validation on the parameters
return true; //return true for now
}).WithMessage("The parameters are not valid");
In this case the method SomeMethodWithParameters has the signature
public void SomeMethodWithParameters(int index, object target)
{
}
What I have right now for registering validation for individual parameters looks like this:
UI.Map<Foo>().Action<int, object>(x => x.SomeMethodWithParameters).GetParameter("index").Validate((val) =>
{
return true; //valid
}).WithMessage("index is not valid");
What I'd like it to be is:
UI.Map<Foo>().Action<int, object(x => x.SomeMethodWithParameters).index.Validate((val) =>
{
return true;
}).WithMessage("index is not valid");
This works using dynamics, but you lose intellisense after the reference to index - which is fine for now. The question is is there a clever syntactical way (other than the ones metioned above) to get Visual Studio to recognize the type somehow. Sounds so far like the answer is "no".
It seems to me that if there was a generic version of IDynamicMetaObjectProvider,
IDynamicMetaObjectProvider<T>
this could be made to work. But there isn't, hence the question.
In order to get intellisense, you're going to have to cast something to a value that is not dynamic at some point. If you find yourself doing this a lot, you can use helper methods to ease the pain somewhat:
GetFoo(dictionary.Foo).SomeMethod();
But that isn't much of an improvement over what you've got already. The only other way to get intellisense would be to cast the value back to a non-dynamic type or avoid dynamic in the first place.
If you want to use Intellisense, it's usually best to avoid using dynamic in the first place.
typedDictionary["foo"].SomeMethod();
Your example makes it seem likely that you have specific expectations about the structure of your dynamic object. Consider whether there's a way to create a static class structure that would fulfill your needs.
Update
In response to your update: If you don't want to drastically change your syntax, I'd suggest using an indexer so that your syntax can look like this:
UI.Map<Foo>().Action<int, object>(x => x.SomeMethodWithParameters)["index"].Validate((val) => {...});
Here's my reasoning:
You only add four characters (and subtract one) compared to the dynamic approach.
Let's face it: you are using a "magic string." By requiring an actual string, this fact will be immediately obvious to programmers who look at this code. Using the dynamic approach, there's nothing to indicate that "index" is not a known value from the compiler's perspective.
If you're willing to change things around quite a bit, you may want to investigate the way Moq plays with expressions in their syntax, particularly the It.IsAny<T>() method. It seems like you might be able to do something more along these lines:
UI.Map<Foo>().Action(
(x, v) => x.SomeMethodWithParameters(
v.Validate<int>(index => {return index > 1;})
.WithMessage("index is not valid"),
v.AlwaysValid<object>()));
Unlike your current solution:
This wouldn't break if you ended up changing the names of the parameters in the method signature: Just like the compiler, the framework would pay more attention to the location and types of the parameters than to their names.
Any changes to the method signature would cause an immediate flag from the compiler, rather than a runtime exception when the code runs.
Another syntax that's probably slightly easier to accomplish (since it wouldn't require parsing expression trees) might be:
UI.Map<Foo>().Action((x, v) => x.SomeMethodWithParameters)
.Validate(v => new{
index = v.ByMethod<int>(i => {return i > 1;}),
target = v.IsNotNull()});
This doesn't give you the advantages listed above, but it still gives you type safety (and therefore intellisense). Pick your poison.
Aside from Explict Cast,
((FooClass)dictionary.foo).SomeMethod();
or Safe Cast,
(dictionary.foo as FooClass).SomeMethod();
the only other way to switch back to static invocation (which will allow intellisense to work) is to do Implicit Cast:
FooClass foo = dictionary.foo;
foo.SomeMethod().
Declared casting is your only option, can't use helper methods because they will be dynamically invoked giving you the same problem.
Update:
Not sure if this is more elegant but doesn't involve casting a bunch and gets intellisense outside of the lambda:
public class DynamicDictionary<T>:IDynamicMetaObjectProvider{
...
public T Get(Func<dynamic,dynamic> arg){
return arg(this);
}
public void Set(Action<dynamic> arg){
arg(this);
}
}
...
var dictionary = new DynamicDictionary<FooClass>();
dictionary.Set(d=>d.Foo = new FooClass());
dictionary.Get(d=>d.Foo).SomeMethod();
As has already been said (in the question and StriplingWarrior answer) the C# 4 dynamic type does not provide intellisense support. This answer is provided merely to provide an explanation why (based on my understanding).
dynamic to the C# compiler is nothing more than object which has only limited knowledge at compile-time which members it supports. The difference is, at run-time, dynamic attempts to resolve members called against its instances against the type for which the instance it represents knows (providing a form of late binding).
Consider the following:
dynamic v = 0;
v += 1;
Console.WriteLine("First: {0}", v);
// ---
v = "Hello";
v += " World";
Console.WriteLine("Second: {0}", v);
In this snippet, v represents both an instance of Int32 (as seen in the first section of code) and an instance of String in the latter. The use of the += operator actually differs between the two different calls to it because the types involved are inferred at run-time (meaning the compiler doesn't understand or infer usage of the types at compile-time).
Now consider a slight variation:
dynamic v;
if (DateTime.Now.Second % 2 == 0)
v = 0;
else
v = "Hello";
v += 1;
Console.WriteLine("{0}", v);
In this example, v could potentially be either an Int32 or a String depending on the time at which the code is run. An extreme example, I know, though it clearly illustrates the problem.
Considering a single dynamic variable could potentially represent any number of types at run-time, it would be nearly impossible for the compiler or IDE to make assumptions about the types it represents prior to it's execution, so Design- or Compile-time resolution of a dynamic variable's potential members is unreasonable (if not impossible).
I thought i've seen it all but this... :)
I was working on a generic graph of type string,
Graph<string> graph = new Graph<string>();
Graph is declared with a class constraint like this:
public class Graph<T> where T : class
Next i fill up the graph with some dynamicly generated strings:
for (char t = 'A'; t < 'J'; t++)
{
GraphPrim.Add(t.ToString());
}
So far so good, (Node is a internal class containing the original value and a list of references to other nodes (because its a graph))
Now, when i try to create relations between the different nodes, i have to look up the right node by checking its value and thats where the weirdness starts.
The following code, is a direct copy of the result found in the immidiate window after doing some tests:
Nodes.First().Value
"A"
Nodes.First().Value == "A"
false
Nodes.First().Value.ToString() == "A"
true
Am i totally missing something or shouldn't Nodes.First().Value == "A" use a string comparison method. (The JIT compiler has knowledge about the type beeing used on runtime, and with that, its supported methods, right?). It seems to me like when not explicitly specifying a string, it will do a reference check rather then a string test.
It would be great if someone could explain this to me,
Thanks in advance!
If the types aren't fully known up front (i.e. Value is only known as T, and is not strictly known to be a string), use things like:
object.Equals(Nodes.First().Value,"A")
Of course, you could cast, but in this case you'd need a double-cast ((string)(object)) which is ugly.
If you know the two objects are the same type (i.e. two T values), then you can use:
EqualityComparer<T>.Default.Equals(x,y)
The advantage of the above is that it avoids boxing of structs and supports lifted Nullable<T> operators, and IEquatable<T> in addition to Equals.
If the Value property of your Nodes is object, the == operator in
Nodes.First().Value == "A"
will do a comparison by reference instead of comparing strings.
== is a static method and therefore not virtual. The selection of which == method to use is done at compile-time, not run-time. Depending on the compile-time type of the object, it is probably choosing the implementation of == for objects that compares by reference.
If you use the virtual Equals methods instead, this will work as you expect.
I'm curious about how some operators work (+, -) in terms of objects.
I've always wondered how EventHandlers work by adding a method:
Foo.Action += new FooActionHandler
If not an Event, what about returning a comparison?
DateTime - DateTime
That returns a TimeSpan object, and I'm a bit baffled as to how that's possible. I use these kinds of methods all the time but I've never understood the inner workings of them. How would I create my own class to do something like this?
You can overload operators to perform whatever action you want. Here is some good documentation for how to do it in C#.
The gist of it is that you provide a context for the operator (your class) and what occurs with the parameters to it. A sample might look like this:
// Overload '+' for my class
public static MyClass operator +(MyClass c1, MyClass c2)
{
MyClass newMyClass = new MyClass();
newMyClass.MyIntProperty = c1.MyIntProperty + c2.MyIntProperty;
return newMyClass;
}
You can define operators like this:
public static MyClass operator +(MyClass a, MyClass b) { }
With the same syntax for -, *, etc.
Here are some tips (my opinion, mostly):
Don't put the actual logic in the operator - create a static method.
// NOT
public static MyClass operator +(MyClass a, MyClass b) { /* ... */ }
// YES
public static MyClass Add(MyClass a, MyClass b) { return new MyClass(a.Prop + b.Prop); }
public static MyClass operator +(MyClass a, MyClass b) { return Add(a, b); }
Don't bend the operators to do something they shouldn't - ie, don't use + to add to a list, or - to remove from a list, for example.
This causes two problems:
It isn't very well-regarded in the community
The compiler won't catch errors if you accidentally add two objects.
This is called operator overloading. Google will return many articles that explain how it works, and when to use and not use it.
http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=88
Here ya go: http://msdn.microsoft.com/en-us/library/aa288467(VS.71).aspx
It is called operator overloading. C# allows you to overload select operators.
There is more information on this here.
You can overload an operator to do whatever you want.
Lets say I have a Truck Class, and MachineGun class, I want to be able to do this:
Transformer myTransformer = mytruck + myGun;
the += and -= for EventHandlers are shortcuts for Delegate.Combine and Delegate.Remove, this is accomplished with operator overloading, see this site for more details.
This is known as operator overloading. It's used by the framework extensively, however you should avoid doing it since it can lead to some bad code if you don't know what you're doing.
Most programmers don't expect to see a custom class with operators being overloaded so it can become maintenance hell when other programmers have to look at your code and figure out what is going on.
Of course, there are situations where you may find it useful, but usually you're better off just using methods instead of creating operator overloads. You can find out more info from Microsoft here:
http://msdn.microsoft.com/en-us/library/aa288467.aspx
Plenty of answers have covered how you do it. Now just remember that you'll almost never want to actually do it yourself. You need to be really sure that anyone using your class will agree with you about what subtracting two MyClass objects means. If it represents some kind of mathematical structure (vector, matrix, etc) then you're probably safe. Otherwise, it's probably unclear. Notice that Microsoft defined subtraction for DateTime, but didn't allow
List<string> myList = new List<string>();
myList += "foo";
Any time you write
static Foo operator -( Foo a, Foo b )
then think about what you'd call that method if you couldn't override subtraction. If the best possible name isn't Subtract, then you probably want to just create a method with that other name.