Random cool C# stuff
I get a kick out of finding useful little language features, and since a large part of this community is on Unity/C# projects, I'm hoping this isn't totally out of place. Actually, I hope it'll actually be useful to some people :) I'm pretty sure @HermanTulleken and @Chippit will have tons of stuff to add here as well ;)
So this morning I found a cool trick with concrete generic parameters and extension classes. The problem this solves for me (in some cases) is one of not being able to specify something like a "numeric" generic constraint, so this won't work:
Now if it happens that the method you're implementing is on a generic class with the numeric type as it's type parameter, you can implement extension methods with a concrete typed version of the generic class as a parameter. Here's a (contrived) example:
Now it can be used like this:
Obviously you still end up implementing the method for each type you'd want to use it for, but at least you don't have to reimplement the rest of the class.
So this morning I found a cool trick with concrete generic parameters and extension classes. The problem this solves for me (in some cases) is one of not being able to specify something like a "numeric" generic constraint, so this won't work:
public static T Max<T>(T t1, T t2) { return (t2 > t1)?t2:t1; }
Now if it happens that the method you're implementing is on a generic class with the numeric type as it's type parameter, you can implement extension methods with a concrete typed version of the generic class as a parameter. Here's a (contrived) example:
public class Range<T> where T : IComparable<T> { public T Min { get; set; } public T Max { get; set; } public bool ContainsValue(T value) { return (Min.CompareTo(value) <= 0) && (value.CompareTo(Max) <= 0); } } public static class RangeTypeExtensions { public static float GetRandomValue(this Range<float> range, Random random) { return random.Next(range.Min, range.Max); } public static int GetRandomValue(this Range<int> range, Random random) { return random.Next(range.Min, range.Max); } }
Now it can be used like this:
var random = new Random(); var range = new Range() { Min = 0.0f, Max = 1.0f }; float valueInRange = range.GetRandomValue(random);
Obviously you still end up implementing the method for each type you'd want to use it for, but at least you don't have to reimplement the rest of the class.
Comments
Learned today the enums can have extension methods which means you can have something like
I am struggling to contain my excitement at this discovery ... srsly guise
*ahem cough cough* ... yeah it's pretty fun...
The reason it breaks is that, despite what Unity wants you to believe, due to how the internal Unity engine operates (and probably because of how its .NET script interface works) references to MonoBehaviour objects are rarely ever actually null. All MonoBehaviours, however, override ToString, Equals and have an explicit bool conversion (eeeuuugh) that makes them appear as if they are under certain circumstances.
If you destroy a game object or script, the script references will appear to be null. Which is to say
The above is also true if a game object or script is not assigned in the editor.
However, those objects are not actually null references
So that won't work, because the null coalescing operator sidesteps the Equals override by using (I believe) the generic comparator that other things like Dictionaries also use.
Basically, the tl;dr here is that ?? won't work for Unity objects. Don't use it unless you want to fight with really, really arb issues down the line.
Another interesting one with extensions is that interfaces can have them. So if there's functionality you want all implementations of an interface to have (without explicitly implementing it) that is based on simpler methods they implement as part of the interface, you can add it as an extension to the interface:
(example from http://www.zorched.net/2008/01/03/implementing-mixins-with-c-extension-methods)
[rant]
There's value in being cautious about new features, but these features usually exist for a good reason (especially in a design-by-committee language like C#). If you don't at least consider how they might be useful, you might be missing out on something that could genuinely improve the quality, readability and even performance of your code. Over my years in dev, too often I've seen "old skool" seniors avoid new ways of doing things simply because they're not "old skool". IMO, as a lead/senior dev it's your responsibility to constantly evaluate how you're doing things and improve both your and your team's approach. Lack of this approach, and paranoia about performance without actually testing is why from a code practice point of view game dev is often far behind the curve. Game developers had to be dragged from C to C++, long after the performance concerns were dealt with, then again to using templates, and then again to using managed languages. Some still use C# as if it was C++ with a garbage collector (which leads to it's own issues, because it really isn't as simple as all that).
[/rant]
@Elyaradine, I read something recently that said that code gets read far more often than it gets written. So it's worth it to take the time to write something that is easier to read(which means I'm agreeing with you :P). I am beginning to dislike "clever" code more and more. I'd rather have something that reads as close to pseudo code/English as possible. I'm working hard to get myself there(not nearly there yet unfortunately).
Please keep posting stuff here everyone. I at least appreciate this a lot even tough(or especially since) I don't have anything to add(yet).
"I don't have anything to add(yet)"
You are such a liar!
----
What you say about reading vs. writing is very true. It's the same as writing really readable English: it's damn hard. And language features help, but not as much as you'd imagine. Because writing good code requires thinking, not writing. It also requires something else: caring. (I have read some writer said to be a good writer, you have to be a good person, because only if you care about other people, are you able to spend the time necessary to write clearly. I think it applies doubly so to programmers.).
----
I am totally dependent on extension methods; they are really cool.
I have a variety of extensions on Unity structs (Transform.SetXY, Transform.AddZ, Color.Lighter, Vector.PerpDot, Vector.Reflect(...), and a tonne on IEnumerator (SampleRandom, SampleGrid, SampleJitteredGrid, Closest, Farthest, InRange, OfType, WhereNotNull, Last, ButFirst, ButLast, ToListString, Combination, Permutation etc.), some on random (mostly for generating point types and tuples) and some for debugging such as these:
The mixin pattern is particularly useful for structs, since structs cannot share common implementation.
Extension methods also help keep hierarchies flat, and together with the mixin pattern, allows you to keep behaviours in small modules. In very generic code this reduces the number of type parameters you need to specify for methods (see also below).
In Grids we also use the following pattern frequently:
so that methods can be declared with specific types, rather than base types. (For example, you can define Add in the base class, but have the subtype returned when called on a subtype, not the base type) This reduces casting a lot in certain cases, and provides a layer of type safety without giving up shared implementation. (The pattern is also the typical way C# Singletons are implemented as a single base class; all that a class has to do to be a singleton is extend from this class.). (Some people consider this pattern an antipattern, since you don't quite get what you expect. You could conceivably make a class class Z : X<Y> {}, for which it is unclear how the classes relate. I think, however it's utility outweighs this danger).
(If you use this heavily, you may end up with extremely complicated type definitions, and it's the same type of feeling you get trying to write a const correct program in C++. In this case, its well worth it to define methods as extension methods to reduce the number of types you have to specify).
@mattbeinc
"C to C++, long after the performance concerns were dealt with, then again to using templates, and then again to using managed languages." And then from for to foreach ;--) (jk). But I agree with what you are saying. And in the case where there is performance at stake it's one thing, but we also lag behind in software design concepts. Singletons just became popular in game dev when they started to fall out of fashion in the corporate world... Not to mention tools... ;_;
Enough philosophical griping, here's another morsel: indexed properties using an inner class. This is one of those that has the potential to be misused and hamper rather than help readability, but in the right contexts it can be useful.
The problem it solves is the lack of indexable properties in c#. The following isn't valid:
In simple cases, you might have a collection you're returning directly, but (a) that could have access issues (b) sometimes it's not just a simple collection. Also, usually just using a get method (like the one called above) is fine. In some cases though, in would be really nice to just use an indexer shorthand. A real world example in our case is string localization. We have different language localizers per client and If we had to repeatedly use something like Language.Instance.GetLocalizedString(), it really would impact our code readability a lot.
One way around this is to use an inner class's indexed this operator:
This may seem like a lot of code to do something really simple, and as I warned above has the potential to be less readable. But at the end of the day the benefit is cleaning up the code that uses it, by being able to do this:
In our case we have an UpperStrings as well that uses the same approach and wraps some client specific uppercasing behavior, but is just as clean to use.
Also mini rant on the fact that c# has so much deliciousness that is just a bad idea on mobile. Lambda syntax and reflection being at the top of the list. Makes me sad.
@mattbenic thanks for that tip on specifying a base type for a generic. I was looking for that a while back when porting some Java io code to Unity. Could not find it back then haven't looked since. I can not tell you how many of the structures I typically have been pointless without this. There is nothing wrong with using reflection on mobile if you stick to the one thing reflection is best at, factories. Been able to build scripts based on data without having to have a massive long switch statement is absolutely awesome. Of course you could build a long enum with the build methods in it, but that doesn't always work for all cases. The Lambda syntax I would cation against for now mostly due to memory constraints more then performance. Performance can be managed by doing the work at a suitable time, memory can not.
On the readability of code issue I have never rushed to nor specifically delayed adopting new syntax. When that syntax is more then just sugar I do tend to be cautious and want to know what it does under the hood before adopting it outright. I find that the OO structures and the manner in which they interact is something far more difficult for new developers to pick up then simple syntax stuff. (I will admit I have become a bit lazy about building my OO interaction diagrams. I still prefer Booch notation. http://en.wikipedia.org/wiki/Booch_method although UML sequence diagrams for closer design of interactions is awesome. I think puffy clouds just feel more like gamedev then hard square edges I also feel Booch communicates more visually while UML more in words.) I think its high time I start investigating the c# code documentations tools similar to JavaDoc I am used to been able to pull a very comprehensive code guide with diagrams from my code rather then having to maintain them separately. When I was at Psygnosis's Liverpool offices years ago chatting with there Lead Dev he has actually chosen to ban the developers from using templates due to multiple nested templets adding to the total code size quickly as well as often creating situations where the developers could not adjust one behavior without pulling the whole thing down. His issue at the time was less to do with the technology and more to do with the haphazard manner in which it was been applied. I for one am a far bigger fan of generics then templets. I had singletons in both Toxic Bunny and The Tainted (Although I don't suspect we had called them singletons yet early 1990's was really the beginning of the OO adoption in mainstream). Will admit I am still using them now and more then I would like its just so damn convenient sometimes. In Unity I am moving from singletons to instances on named GameObjects that persist. It gives me a nice way to create alternative start scenes where I can adjust the settings of each object and also a convenient way to have multiple instances. In my limited experience gamedev are the early adopters not the late ones. Perhaps that's changed if so its disappointing. I saw many gamedevs pushing to include managed languages into there games Java been one of them LAU was created for just that (20 years ago) and to make some of the messy code more manageable.
If I may ask a few questions I have since I am coming from a Java background there are still some things I am used to having that I haven't found suitable replacements for in c# yet.
In Java a nested inner class not specifically declared as static is automatically considered to be part of the parent and all instances gain intimidate access to the parent class.
The example is bogus, but the point is its often useful to be able to expose some methods in the factory parent that all the classes it builds can access without having to expose those methods to everyone. Is there a convenient way to do this in c# in java its the inner class in c++ I would just declare the base class of the children as a friend. In c#?
I'm a big fan of creating neat, readable, loosely coupled and maintainable code (specifically SOLID principles and Gang of Four Design patterns).
In our world maintainability means the whole team (consisting of various skill leveled programmers) need to work together.
Where our client's client is SARS, where deadlines aren't negotiable estimations, but fixed targets.
Also we've had a scenario where a lead developer over-engineered a module (job security?) using all the new generation C# features and fancy tricks. We had to re-factor his work so that it was simpler to understand and easier to maintain.
So it is within that context that I raise my concerns re: new language features and getting fancy. Yes some are useful and I get an endorphin buzz when it builds :-P
Also, IMHO some of these new powerful features do NOT make the code more readable - just look at LINQ lambda expressions for example.
Conciseness, yes - Readability? Erm, no. So horses for courses. ;)
PS: I'm not shooting down this thread, just adding a different perspective.
I avoid linq in any realtime code, simply because of the additional garbage generation, but I'm happy to use it in loading and tool scenarios. Besides being less garbage sensitive, this also tends to be code that would need reworking anyway in case of a technology change. I know @hermantulleken is a total linq fanboi ;)
Here's an example where personally I think the code is far more concise and readable than the non-linq alternative, but I also know some devs that haven't used linq might disagree. To me this is more like the pure logic of what I want to achieve, than a bunch of nested fors:
1. If the case allows for it, declare the field or method you want exposed to the inner class private static:
The difference here looks like java inner class instances implicitly have a reference to their outer class instance they are related to (don't remember that..), while inner class instances in C# are in no way related to a particular instance of the outer class.
2. Give the inner class a reference to the outer class:
If you're concerned about circular references here, use a WeakReference. If you want this access passed on to children of the inner class, you'll basically need to wrap access to the private stuff in the outer class in protected methods on the inner class.
Also, you get to absorb some stuff working with other programmers (although because all the gamedev companies are so small, the opportunity is rare). And for game dev specific stuff, you will have to just invent some patterns and idioms on your own. The way we need to solve difficult problems across several frames, and our more complicated logic visualisation (thinking here of things like transitions, and use of randomness to spice things up), for example, are a bit different from problems in other fields. You need not worry about it for the sake of GC though.
http://stackoverflow.com/questions/9604197/circular-reference-in-same-assembly-a-bad-thing
However phrases like: still worry me a little because I don't know how true that is in Mono or compact framework in general. I know in The Harvest we had a tons of circular references in our scene graph (this was just one of those C++ to a garbage collected language things that happened a lot) and it did actually cause leaks between scenes on the then-WP7 compact framework. This may have been the complexity of the graph confusing the GC though, and not a failing in the GC itself. Definitely something I need to test sometime in Mono/Unity.
Namespaces in C# are like packages in Java, they just serve to separate classes into logical collections. In Java, if no access modifier (private, protected, public) is specifed, the default is package-private access (reference), there is no equivalent access modifier in C#.
Assemblies on the other hand are essentially compiled binary files containing collections of usable classes, for our purposes they are dlls or exes containing our compiled code. C#'s internal modifier limits access to other classes in the same assembly.
The reason I say using different assemblies is a pain in the ass is Unity has it's own way of breaking up your code into assemblies based on their compilation order-the dll projects in your monodev or VS solutions represent these assemblies. As far as I'm aware, the only way to introduce other assemblies into the mix is as precompiled dlls, or by setting up your own custom solution and working on individual projects there. I may be wrong, and there may be an easy way to introduce additional assembly projects to the autogenerated (by Unity) solutions without having to re-add them every time Unity changes them.
But read @Chippit's response post, it will NOT work with any Unity Component/MonoBehaviour or GameObject (I think anything derived from UnityEngine.Object)
literally yesterday I was like harharhar I'm going to use the ?? operator and it'll work just fine harharhar ...
so be careful with it, mkay :)
@raxter what version of Unity did you use?
And now I did a another test and it seems not all components are equal: if fails with Transform, but not my own MonoBehaviour... The inconsistency makes it pretty useless.
(Edit: More interesting than useful, it seems to work for MonoBehaviour itself, but not Component or Behaviour)
Hmmm did I do something stupid?
http://roslyn.codeplex.com/
If you have a generic class like this:
And then you use it in a MonoBehavior or ten:
Unity, quite stupidly, doesn't display the generic fields in the inspector even though the concrete types of Min and Max would be known at compile time.
Thankfully, there's a workaround. You can create concrete subclasses of the generic, also with the Serializable attribute, and Unity will correctly display them:
Don't forget to update your monobehavior..
Now this may seem to defeat the point of generics somewhat, but at least you're not re-implementing all your useful functionality, and when you need a new concrete type, you just need to add a new subclass.
Also, if you're using var in local scope, the only place you should ever need to use these subclasses is in the fields actually exposed in the inspector. If you're really pedantic, you could even keep those private (and use UnityEngine.SerializeField), and rather expose them to code with a property that uses the base template type:
Both the ContainsKey and index operators -and pretty much anything else you'd expect to do with a dict- will cause boxing of the key value, and thus generate garbage. This is because by default the dictionary uses EqualityComparer.Default, which in turn uses Object.Equals and Object.GetHashCode to get hash keys and determine equality.
Unfortunately there doesn't seem to be an elegant generic solution that doesn't also box or otherwise allocate (there's one in the comments of this article that generates the necessary IL opcodes directly, but without testing it on Unity in general and iOS in particular I wouldn't jump at suggesting it). So what you need to do is create an IEqualityComparer implementation for each enum you want to use as a dictionary key (often enough to care about the allocations), and pass it to the dictionary:
I'm not speaking about hypothetical risks here either :) I've had to deal with cases in my current project where assumptions around converting to int and then back to a different enum have led to nasty, hard to find issues.
http://gamelogic.co.za/2014/01/11/workarounds-for-aot-compiler-limitations/
Another possible solution though is an old C hack that uses the enum as an index into an array. It's much faster than dictionary lookups but is only feasible if you anticipate most of the keys will have values, and the members of the enum have sequential integral values that start at 0 (it also involves casting which will put some folks off).
The array option is of course a perfectly valid alternative, the only reason we really use a dict is convenience. You could probably write a dict like wrapper around an array specifically for enums that would have the same convenience and none of the performance concerns, and wouldn't need the above workaround.