C# 4: Generic variance for delegates

Here are some experiments regarding variance of type parameters for generic delegates in C# 4. There are two kinds of variance: covariance and contravariance. I think of variance as using extended type in place of base type (you could visualise it as a UML diagram, where extended type points to base type). Contravariance is just the opposite: using base type in plase of extended type.

If delgate’s type paramter is variant, it means that we can assign a delegate instance with diffrent type paramter to delegates variable.

Some basic delgates types with variant paramters in C# are Func and Action, simplest of which are:
delegate void Action<in T>(T obj), where in T is contravariant parameter
and
delegate TResult Func<out TResult>(), where out TResult is covariant parameter.

It gets pretty funny when it turns out, that in some cases the default variance type can be inverted when delegate type (with variant type paramter) is nested in another delegate type (i.e. when delegate with variant type paramter becomes a parameter for another delegate). Before showing some cases, let’s bring up a terse rule from a great book “C# in depth” by Jon Skeet: “As a quick rule of thumb, you can think of nested contravariance as reversing the previous variance, whereas covariance doesn’t, so whereas Action<Action> is covariant in T, Action<Action<Action>> is contravariant. Compare that with Func variance, where you can write Func<Func<Func<...Func<T>...>>> with as many levels of nesting as you like and still get covariance”.

For the sake of latter examples, let’s assume that we have a following class hierachy:

Object <- Person <- Child

Let’s start with simple Func covariance:

Func<object> objectOutputFunc = () => new object();
Func<Person> personOutputFunc = () => new Person();
Func<Child> childOuputFunc = () => new Child();
// delegate expected to return Person can return Child
personOutputFunc = childOuputFunc;
personOutputFunc = () => new Child();
// won't compile: personOutputFunc = objectOutputFunc;
// won't compile: personOutputFunc = () => new object();

And some obvious behavior of Action covariance:

// an action, which will be fed with object
Action<object> actionObject = new Action<object>(o => Console.WriteLine(o));
// an action, which will be fed with Person
Action<Person> actionPerson;
// an action, which will be fed with Child
Action<Child> actionChild;
// wont compile (syntax): actionPerson = (Object o) => Console.WriteLine(o);
// an action which expects an object can be fed with a person
actionPerson = actionObject;

//actionPerson(obj);
actionPerson(person);
actionPerson(child);

As noted earlier, nesting Func inside Func does not change type paramter variance (i.e. T in Func<Func<Func<...Func<T>...>>> is always contravariant).

Let’s check what happens when we nest Action inside Func:

Func<Action<object>> funcActionObject = () => o => Console.WriteLine(o);
Func<Action<Person>> funcActionPerson = () => p => Console.WriteLine(p);
Func<Action<Child>> funcActionChild = () => c => Console.WriteLine(c);

// action type parameter is contravariant and so it is here
funcActionPerson = funcActionObject;

Func<Func<Action<object>>> funcFuncActionObject = () => () => o => Console.WriteLine(o);
Func<Func<Action<Person>>> funcFuncActionPerson = () => () => p => Console.WriteLine(p);
Func<Func<Action<Child>>> funcFuncActionChild = () => () => c => Console.WriteLine(c);

// action type parameter is contravariant and so it is here
funcFuncActionPerson = funcFuncActionObject;

Func did not change variance o Action parameter, so Jon Skeet’s rule still applies (that should be no surprise).

Now, let’s see how Action changes variance of nested Func:

Action<Func<object>> actionFuncObject = (f) => f.Invoke();
Action<Func<Person>> actionFuncPerson = (f) => f.Invoke();
Action<Func<Child>> actionFuncChild = (f) => f.Invoke ();

// won't compile: actionFuncPerson = actionFuncChild;

// normally, func is covariant,
// but here, type parameter became contravariant
actionFuncPerson = actionFuncObject;
// won't compile: actionFuncPerson = (Func<object> f) => f.Invoke();
Action<Func<Func<object>>> actionFuncFuncObject = (ffo) => ffo.Invoke().Invoke();
Action<Func<Func<Person>>> actionFuncFuncPerson = (ffp) => ffp.Invoke().Invoke();
Action<Func<Func<Child>>> actionFuncFuncChild = (ffc) => ffc.Invoke().Invoke();

// normally, func is covariant,
// but here, type parameter became contravariant
actionFuncFuncPerson = actionFuncFuncObject;
// won't compile: actionFuncFuncPerson = (Func<Func<object>> ffo) => ffo.Invoke().Invoke();

Indeed, when nesting Func inside Action, variance of type parameter of nested Func changed.

Finally, let’s check how type parameters variance change when nesting sequences of Actions:

// ======== Action<Person> fun ========
// action expects an object to work on.
// actual object to work on is supplied in place of action invocation

// an action, which will be fed with object
Action<object> actionObject = new Action<object>(o => Console.WriteLine(o));
// an action, which will be fed with Person
Action<Person> actionPerson;
// an action, which will be fed with Child
Action<Child> actionChild;

// wont compile (syntax): actionPerson = (Object o) => Console.WriteLine(o);
// an action which expects an object can be fed with a person
actionPerson = actionObject;

//actionPerson(obj);
actionPerson(person);
actionPerson(child);

// ======== Action<Action<Person>> fun ========
// action expects another action which will be suplied with the object by the first action.
// actual object to work on is supplied in place of action definition

// an action, which will be fed with an action for object
			Action<Action<object>> actionActionObject;

// an action, which will be fed with an action for person
Action<Action<Person>> actionActionPerson;

// an action, which will be fed with an action for child
Action<Action<Child>> actionActionChild = new Action<Action<Child>>(a => a.Invoke (child));

// an action, which expects an action to which it may pass a child,
// can be fed with an action which expects a person
actionActionPerson = actionActionChild;
actionActionPerson(new Action<object>(o => Console.WriteLine("Object: " + o))); 
actionActionPerson(p => Console.WriteLine("Person name: " + p.Name));  
//actionActionPerson(new Action<Child>(c => Console.WriteLine("Child toys: " + c.NumberOfToys)));  
actionActionChild(new Action<Child>(c => Console.WriteLine("Child toys: " + c.NumberOfToys)));  

// ======== ActionAction<<Action<Person>>> fun ========
// action (1) expects another action (2), which will be suplied with another action (from action 1) 
// and that another action will work on parameter supplied "within" action (1).
// actual object to work on can be supplied in place of action invocation (simplest case).

Action<Action<Action<object>>> actionActionActionObject = a => a.Invoke(o => Console.WriteLine("Tripple action: " + o));
Action<Action<Action<Person>>> actionActionActionPerson;
Action<Action<Action<Child>>> actionActionActionChild;

actionActionActionObject(ao => ao.Invoke(obj));
actionActionActionPerson = actionActionActionObject;
actionActionActionPerson(ap => ap.Invoke(person));

// ======== ActionActionAction<<Action<Person>>> fun ========
			
Action<Action<Action<Action<object>>>> actionActionActionActionObject;
Action<Action<Action<Action<Person>>>> actionActionActionActionPerson;
Action<Action<Action<Action<Child>>>> actionActionActionActionChild = a => a.Invoke(a2 => a2.Invoke(child));
			
actionActionActionActionChild(a => a.Invoke(c => Console.WriteLine("Quadruple action: Child toys: " + c.NumberOfToys)));
//actionActionActionPerson = actionActionActionActionChild;
//actionActionActionPerson(ap => ap.Invoke(person)); 

Hope you had fun!

Advertisements

Leave a comment

WinDbg SOS cheatsheet

SOS (Son of Strike) WinDbg extensions allows you to debug (and monitor resource usage, find leaks, help spot deadlocks) .NET applications. Here are some useful SOS commands which may be executed in WinDbg or Visual Studio’s immediate window. All SOS command can be found here:¬†https://msdn.microsoft.com/en-us/library/bb190764(v=vs.110).aspx

.loadby sos clr
loads SOS extension

.cls
clears the screen

Memory stuff:

!eeheap -gc
information about managed heap

!dumpheap -stat
lists loaded classes, number of instances of each class and addres of Method Table (MT)

!dumpheap -mt [MT]
dumps objects of given class (i.e. of class which has method table at address)

!do [object's address]
dumps particular managed object

du [object's address]
dumps particular not-necessarily managed object

!gcroot [object's address]
shows reference chain to given object

Stack stuff:

~* e !clrstack
for every (*) thread (~) execute (e) command !clrstack (which prints current stack)

!syncblock
lists synchronization blocks owned by active threads (.i.e you may check if some thread is being blocked)

~30s
prints information about thread 30 and sets current “debugging context” to thread 30, so then one can call

!clrstack
to print stack for previously set thread

!threadpool
threadpool info

!threads

~* kb
prints native stack for all threads

Leave a comment

iOS and OS X: Utility class for accessing NSManagedObjectModel and NSManagedObjectContext

Some projects templates by XCode wizards provide code for accessing NSManagedObjectModel and NSManagedObjectContext, but some other do not. In case of projects which were not provided with auto-generated code for accessing model data, here is a class (based on these auto-genereted stuff) which accesses NSManagedObjectModel and NSManagedObjectContext. For the code to work properly, values for field “objectModelFileName” and “bundleIndentifier” have to be provided. For example, if name of file with model data is “MyApp.xcdatamodelId”, then “objectModelFileName” should have value “MyApp” and “bundleIndentifier” should have value which is equal to name of the application’s bundle name.

Header:

#import <Cocoa/Cocoa.h>

@interface ManagedObjectContextProvider : NSObject

@property (retain, nonatomic) NSString *objectModelFileName;
@property (retain, nonatomic) NSString *bundleIndentifier;

@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;

@end

Class definition:

#import "ManagedObjectContextProvider.h"

@implementation ManagedObjectContextProvider

@synthesize objectModelFileName = __objectModelFileName;
@synthesize bundleIndentifier = __bundleIndentifier;

@synthesize persistentStoreCoordinator = __persistentStoreCoordinator;
@synthesize managedObjectModel = __managedObjectModel;
@synthesize managedObjectContext = __managedObjectContext;

// Returns the directory the application uses to store the Core Data store file. 
- (NSURL *)applicationFilesDirectory
{
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSURL *appSupportURL = [[fileManager URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask] lastObject];
    return [appSupportURL URLByAppendingPathComponent:__bundleIndentifier];
}

// Creates if necessary and returns the managed object model for the application.
- (NSManagedObjectModel *)managedObjectModel
{
    if (__managedObjectModel) {
        return __managedObjectModel;
    }
	
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:__objectModelFileName withExtension:@"momd"];
    __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return __managedObjectModel;
}

// Returns the persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. (The directory for the store is created, if necessary.)
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (__persistentStoreCoordinator) {
        return __persistentStoreCoordinator;
    }
    
    NSManagedObjectModel *mom = [self managedObjectModel];
    if (!mom) {
        NSLog(@"%@:%@ No model to generate a store from", [self class], NSStringFromSelector(_cmd));
        return nil;
    }
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSURL *applicationFilesDirectory = [self applicationFilesDirectory];
    NSError *error = nil;
    
    NSDictionary *properties = [applicationFilesDirectory resourceValuesForKeys:[NSArray arrayWithObject:NSURLIsDirectoryKey] error:&error];
    
    if (!properties) {
        BOOL ok = NO;
        if ([error code] == NSFileReadNoSuchFileError) {
            ok = [fileManager createDirectoryAtPath:[applicationFilesDirectory path] withIntermediateDirectories:YES attributes:nil error:&error];
        }
        if (!ok) {
            [[NSApplication sharedApplication] presentError:error];
            return nil;
        }
    } else {
        if (![[properties objectForKey:NSURLIsDirectoryKey] boolValue]) {
            // Customize and localize this error.
            NSString *failureDescription = [NSString stringWithFormat:@"Expected a folder to store application data, found a file (%@).", [applicationFilesDirectory path]];
            
            NSMutableDictionary *dict = [NSMutableDictionary dictionary];
            [dict setValue:failureDescription forKey:NSLocalizedDescriptionKey];
            error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:101 userInfo:dict];
            
            [[NSApplication sharedApplication] presentError:error];
            return nil;
        }
    }
    
    NSURL *url = [applicationFilesDirectory URLByAppendingPathComponent:@"CocoaApp1.storedata"];
    NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
    if (![coordinator addPersistentStoreWithType:NSXMLStoreType configuration:nil URL:url options:nil error:&error]) {
        [[NSApplication sharedApplication] presentError:error];
        return nil;
    }
    __persistentStoreCoordinator = coordinator;
    
    return __persistentStoreCoordinator;
}

// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)
- (NSManagedObjectContext *)managedObjectContext
{
    if (__managedObjectContext) {
        return __managedObjectContext;
    }
    
    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (!coordinator) {
        NSMutableDictionary *dict = [NSMutableDictionary dictionary];
        [dict setValue:@"Failed to initialize the store" forKey:NSLocalizedDescriptionKey];
        [dict setValue:@"There was an error building up the data file." forKey:NSLocalizedFailureReasonErrorKey];
        NSError *error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict];
        [[NSApplication sharedApplication] presentError:error];
        return nil;
    }
    __managedObjectContext = [[NSManagedObjectContext alloc] init];
    [__managedObjectContext setPersistentStoreCoordinator:coordinator];
    
    return __managedObjectContext;
}


@end

Leave a comment

Simple configuration file for a .NET application

In order to read simple “key-value” configuration file for a .NET application, a class shown below may be used:


using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace SomeNamespace
{
    public class SimpleConfigurationManager
    {
        public static string GetConfigurationParameterValue(string key)
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location);
            try
            {
                AppSettingsSection c = (AppSettingsSection)config.GetSection("some_section_in_config_file");
                var i = c.ElementInformation;
                return c.Settings[key].Value;
            }
            catch (Exception e)
            {
                return null;
            }
        }
    }
}

The config file, which will be read by the class:

  1. should be stored in the same directory as the executable file
  2. should be named according to this pattern: executable file name + “.config”, for example: MyApp.exe.config
  3. should have following structure:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="some_section_in_config_file" type="System.Configuration.AppSettingsSection" />
  </configSections>

  <some_section_in_config_file>
    <add key="some_key_1" value="1024" />
    <add key="some_key_2" value="www.google.com" />
    <add key="and_some_other_key" value="true" />
  </some_section_in_config_file>

</configuration>

Leave a comment

Voodoo doll 3D for iOS and Android

I have just finished a Voodoo Doll game. The game simulates a rag doll – you can drag it, burn it with a candle flame, stick with pins and nail to the table. The game was made in Unity3D.

You can download and have fun with the game: Android version.

IMG_0143

photo

, , , ,

Leave a comment

Count number of occurrences of distinct values using LINQ

C# code snippet below finds distinct (case-insensitive) strings in a collection and counts number of occurrences of each unique (case-insensitive again) one.

static void Main(string[] args)
        {

            string[] sa = { "ala", "ma", "ala", "ma", "ma", "abc" };

            var res = from uniqueString
                in sa.Distinct(StringComparer.CurrentCultureIgnoreCase).ToList()
                      select new { str = uniqueString, occur = sa.Count(s => s.ToLower().Equals(uniqueString.ToLower())) };


            foreach(var el in res){
                Console.Write(el.GetType().GetProperty("str").GetValue(el, null) +  "\t");
                Console.WriteLine(el.GetType().GetProperty("occur").GetValue(el, null));
            }

            Console.ReadLine();
        }

,

1 Comment

Blender: Script for exporting models to xml

Python script shown below exports models from Blender 2.44 (but it should work with other versions too) to XML file. the structure of output XML file is something like this:

<objects>
	<object name="Cube">
		<vertices count="18">
			<v>
				<c>
					<x>-0.164879</x><y>0.242091</y><z>-5.895331</z>
				</c>
				<n>
					<x>0.577349</x><y>0.577349</y><z>-0.577349</z>
				</n>
			</v>
			<v>
				<c>
					<x>-0.164879</x><y>-0.524807</y><z>-5.895331</z>
				</c>
				<n>
					<x>0.577349</x><y>-0.577349</y><z>-0.577349</z>
				</n>
			</v>

The script itself is shown below. It can be easily modified in order to produce files of some other structure.

#!BPY

"""
Name: 'To-XML model exporter'
Blender: 244
Group: 'Export'
Tooltip: 'My to-XML model exporter'
"""
import Blender
from Blender import Window
import bpy


print "\n ======== To-XML model exporter ======== "

# just in case - leave edit mode
if Window.EditMode(): 
	print "Forcing to leave edit mode"
	Window.EditMode(0)

# create XML structure
xmlString = "<objects>"

# for each object in the scene
for ob in bpy.data.scenes.active.objects:

	# if this is a mesh
	if ob.type == "Mesh":
		xmlString += "\n\t<object name=\"" + ob.name + "\">"
		
		mesh = ob.getData(mesh=1)
		xmlString += "\n\t\t<vertices count=\"" + ("%d" % (len(mesh.faces) * 3)) + "\">"
		
		allFacesWithNoUV = True
		allFacesWithUV = True
		
		# write down vericles in order how they should be rendered by opengl
		# i.e. if a particualr vertex appears in multiple faces, the vertes is written down multiple times
		for face in mesh.faces:  
			for i in range(0, len(face.v)):
				vertInFace = face.v[i]
				xmlString += "\n\t\t\t<v>"
				
				# write vertilce coords
				xmlString += "\n\t\t\t\t<c>"
				xmlString += "\n\t\t\t\t\t<x>" + ("%f" % mesh.verts[vertInFace.index].co.x) + "</x><y>" + ("%f" % mesh.verts[vertInFace.index].co.y) +"</y><z>" + ("%f" % mesh.verts[vertInFace.index].co.z) + "</z>"
				xmlString += "\n\t\t\t\t</c>"
				
				# write normals
				xmlString += "\n\t\t\t\t<n>"
				xmlString += "\n\t\t\t\t\t<x>" + ("%f" % mesh.verts[vertInFace.index].no.x) + "</x><y>" + ("%f" % mesh.verts[vertInFace.index].no.y) +"</y><z>" + ("%f" % mesh.verts[vertInFace.index].no.z) + "</z>"
				xmlString += "\n\t\t\t\t</n>"
				
				# write texture coords if any
				if hasattr(face, "uv"):
					allFacesWithNoUV &= False # there is a face with uv
					xmlString += "\n\t\t\t\t<uv>"
					xmlString += "\n\t\t\t\t\t<x>" + ("%f" % face.uv[i].x) + "</x><y>" + ("%f" % ( 1.0 - face.uv[i].y)) +"</y>"
					xmlString += "\n\t\t\t\t</uv>"
				else:
					allFacesWithUV &= False # there is a face with no uv
				
				xmlString += "\n\t\t\t</v>"
				
		if not allFacesWithUV and not allFacesWithNoUV:
			print "some faces in object " + ob.name + " are missing uv"
		if not allFacesWithUV:
			print "all faces in object " + ob.name + " are missing uv"
			
		xmlString += "\n\t\t</vertices>"
		xmlString += "\n\t</object>"

xmlString += "\n</objects>"
		
def write(filename):
	outputFile = open(filename, "w")
	outputFile.write(xmlString);
	outputFile.close()
	
Blender.Window.FileSelector(write, "Export")

print "\n ========      end of work      ======== "

, , ,

Leave a comment