Skip to content

c#

These are the stories that have been posted to the c# category.

Constructor Inheritance in C# and Ruby


Published to Invisible Blocks by Dan Bernier June 30, 2008 21:01

This morning: “Surprise!  Want to conduct a job interview?”  I’ve been here a little over 3 months, but um, sure!  “Great.  He’s in the conference room right now.”  Wow, we move quick.

So, without much time to gather my thoughts for good tech-y interview questions, I printed out the resume, and I winged it.  In the middle of the interview, I flipped over his resume, and scribbled out short-hand C# like this:


class A {
   public A() {
      Console.WriteLine("in A");
   }
}
class B : A {
   public B() {
      Console.WriteLine("in B");
   }
}
class C : B {
   public C() {
      Console.WriteLine("in C");
   }
}
new C();

I asked, “What does this print out?” You know, see if he knows which order constructor inheritance goes in. I wanted to hear, “in A, in B, in C”, but not “in C, in B, in A”.

I forget exactly what the candidate’s answer was, but it stirred up a bit of discussion, because the three of us interviewing him disagreed on the answer: one of us said it would only print “in C,” because you need to stick : base() on the B and C constructors for the inheritance to work; I agreed with the third interviewer, who said it would print “in A, in B, in C”, because constructor inheritance is automatic (with no-arg constructors). We fudged around it, laughed a bit, and the interview moved on. (Update: here’s the answer.)

Back at my desk, I had to try it out. I didn’t want to bother with a whole Visual Studio .sln and all that nonsense, so I tried it in Ruby:


class A
    def initialize
        puts "in A"
    end
end
class B < A
    def initialize
        puts "in B"
    end
end
class C < B
    def initialize
        puts "in C"
    end
end

C.new

And the output is…”in C”! Huh? That can’t be right…I was sure constructors were inherited automatically! Then I realized, of course! I’m working in Ruby, and you have to explicitly call superclass methods, constructors included:


class A
    def initialize
        super # <- call the superclass' constructor
        puts "in A"
    end
end
class B < A
    def initialize
        super # <- call the superclass' constructor
        puts "in B"
    end
end
class C < B
    def initialize
        super # <- call the superclass' constructor
        puts "in C"
    end
end

C.new

Stupid Ruby! Did I find a case where C# actually works nicer than Ruby? But then I realized, this also means Ruby lets you change the order of the constructor inheritance: you can go bottom-up, if you want, or even stranger:


class A
    def initialize
        super
        puts "in A"
    end
end
class B < A
    def initialize
        super
        puts "in B"
    end
end
class C < B
    def initialize
        puts "in C"
        super # <- call up the chain AFTER we're done
    end
end

C.new

That one prints out “in C, in A, in B”. The nice thing? No rule to memorize, and more control. The down-side? More to type. But given how compact Ruby already is, I think the added control is worth it here. What do you think?


(Update: I eventually did fire up Visual Studio, and the code above printed “in A, in B, in C”, without me typing out : base(). C# inherits constructors automatically, and the superclass constructors run before subclass constructors.)

Long-running averages, without the sum of preceding values


Published to Invisible Blocks by Dan Bernier July 30, 2008 17:54

Here’s a little lunch-time diversionary math.  Suppose you want a function that takes a number, and returns the average of all the numbers it’s been called with so far.  Handy for continuously updated displays, that kind of thing. Here’s a method that will return this averaging function.


private static Func<float,float> MakeAverager()
{
    float sum = 0;
    int count = 0;
    return delegate(float x)
    {
        sum += x;
        count += 1;
        return sum/count;
    };
}

It creates sum and count variables for the function to close over.  The function takes a number, x, and adds it to sum.  It increments count, and divides.  Pretty standard.

Now, let’s get crazy, and pretend this code is going on Voyager, and it’ll be running for ever.  sum will get pretty high, right?  We’ll blow through 231, the upper-bound for .Net 32-bit ints.  Sure, we could make it a long, and go up to 263, but that’s not the point.  The point is, it’ll eventually run out, because sum is too high.

I’ve been chewing on this brain-teaser for a while.  I knew there must be a way to calculate a long-running average without storing the sum and the count; it seems the average so far, and the count, should be enough, but I don’t want to resort to ((average * count) + x) / count++, because that’s the exact same problem. (Of course, count could still get so high it overflows, but that’s somewhat less likely. Hush, you.)

I finally sat down and figured it out.  The trick is, each successive x tugs your average up or down — first by a lot, but by less over time.  With each x, the average gets harder to move:  the effect each new x has on the average is inversely proportionate to the count.  We can put it like this:

average += (x - average) / count

We tug average by x - average, the distance between them, scaled down by count.  Then, add that on to average (of course, if x < average, then x - average is negative, so it’ll tug the average down).

Let’s make a new averager.


private static Func<float, float> MakeNewAverager()
{
    float average = 0;
    int count = 0;
    return delegate(float x)
    {
        average += (x - average) / ++count;
        return average;
    };
}

It works the same, but it’ll take a lot longer for count to overflow than sum.

For the record, here’s the ruby I used to sketch this idea out.  Of course, in ruby, this problem is even more bogus, because ruby’s Bignum can handle any number that your machine has enough free RAM to store.  But still.


def make_averager
    sum, count = 0, 0
    lambda { |x|
        sum += x
        count += 1
        sum.to_f / count
    }
end

def make_sum_free_averager
    avg = 0.0
    count = 0
    lambda { |x|
        count += 1
        avg += (x - avg) / count
    }
end

Discoveries This Week 04/03/2009


Published to Rick Minerich's Development Wonderland by Richard Minerich April 05, 2009 01:42

With the start of our F# User’s Group this next Monday and New England Code Camp 11 last weekend, things have been extremely busy this past week.  Meanwhile, the F# sociocosm is growing at a rapid pace.  This week we have a talk by Don Syme, a look at F# quotations, and finally, some discussion on Seq.unfold.

 

Chris Bowen’s Post, Announcing F# User Group in Cambridge - April 6

A shameless plug here for our new user group.  A big thanks to Chris for helping us find the resources we needed to start out.  Without him this might never have come together.

 

Don Syme’s Talk, F# and functional programming in .NET

As Don Syme is the father of F#, when he speaks the community listens.  In this talk Don focuses on the pleasure and speed inherent in using FP and F#.  He does this by describing the functional methodology and constructs which provide a simpler and more elegant model for building programs.

 

Alex P’s Post, F# quotations at their simplest

A simple example on the surface for sure.  However, if you haven’t seen the power of F#’s language oriented programming features this is sure to be of interest.

For a deeper look at the power of quotations check out Tomáš Petříček’s F# quotations visualizer.  If his past projects are any indication Tom’s upcoming book is a must have for any F# enthusiast.  I preordered a copy just today.

 

Martin Peck’s Post, Solving Problems in C# and F# - Part 2 
(and update)

One of the most fantastic things F# has to offer is the rich functional programming heritage of sequence operations.  To demonstrate how elegant they can make your code, I would like to offer the following alternative F# solution:

let fibs = 
  Seq.unfold (fun (a, b) -> Some( a, (b, a+b) )) (0I, 1I)
Seq.find (fun n -> n >= 10I ** 999I ) fibs

I’m going to take this opportunity to point out the obvious: we have here two lines of F# which does almost exactly the same thing as thirty six of C#.   Now that’s what I call power and elegance.  The unfold function pretty much does exactly what yield was doing before, but implicitly in terms of the unfold function.  The idea of unfold can be confounding at first and so here is a breakdown of how it works:

let fibs =
  Seq.unfold 
    (fun (a, b) -> //generator function, 
//
(a, b) is the previous state Some //Option monad, needed for unfold (a, (b, a + b))) //returned tuple: (value, state)
//or (
first, (second, third)) (0I, 1I) //Initial function state (first, second)

Note that in this version the state of the next two values in the sequence are always pre-calculated.  However, it is easy to avoid this if you instead consider the state in terms of the previous two values: 

let fibs = 
  Seq.unfold (fun (l, l2) -> 
    let n = l + l2 in Some( n, ( n, l ) ))
    (0I, 1I) //(previous, second previous)

If you want to learn more about unfold I recommend checking out:

 

Dustin Campell’s Post, Apples and Oranges

This is the best description of how unfold works I’ve seen to date. 

 
 

Let’s Wax Functional 03/06/2009


Published to Rick Minerich's Development Wonderland by Richard Minerich March 07, 2009 23:09

This week we have MapReduce, WebTools and yet another F# to C# language comparison.  I spent yesterday at a seminar led by Michael de la Maza.  He, Talbot Crowell and I will soon be starting a F# user’s group in Boston, Massachusetts.  I’m interested in any comments you might have.  Please feel free to send me an email if you would like to discuss speaking at it or content you would like to see covered.

 

Blog - Matthew Podwysocki’s Exploring MapReduce with F#

Google’s MapReduce software framework has revolutionized the way software engineers think about processing large data sets.  Since it’s introduction at least 15 variants have been developed.  Thorough as always, Matthew explores what MapReduce is, how it relates to functional programming and, finally, shows his own light-weight MapReduce implementation.

 

Software – Thomas Petricek’s FSharp.WebTools

The F# Web Tools augment the F# distribution with tools to author homogeneous client/server/database web applications in one type-checked project.

It does this by generating Javascript from F#.  The big advantage here is that you can effectively have statically checked Javascript and so avoid a whole class of bugs that come along with dynamically typed programming.  While many are excited about this prospect, at least one person seems to have had trouble getting it to work.  Currently, only the source tree is available and it must be manually compiled.  I know I’m not the only one hoping for a tested release in the near future.

 

Blog – Martin Peck’s Solving Problems in C# and F# – Part 1

In this post Martin compares solutions to Project Euler problems 10 and 12 in both C# and F#.  In competition with his friend Giles Knap, he wrote his answers in C# while Giles wrote in F#.  Afterward, each set of answers is discussed independently.  He concludes that the languages were equally readable but the F# implementations were slower. 

I wish Giles had written a rebuttal post as Martin seems to be a die hard C# fan.  I don’t agree that they were equally readable.  The F# problems lacked much of the syntactic cruft and whitespace found in the C# examples. 

Also, as single core results are fast becoming meaningless, it would be very if they would agree to use asynchronous workflows in F# and compare that with the .NET Parallel Extensions in C#.  By constraining the answers to be single thread only, it seems like they avoided much of F#’s inherent benefit in multicore processing. 

I also can’t help wondering how each of their prime generating examples would compare with the memoizing example I mentioned two weeks ago.  I’d be shocked to see a similar C# implementation in anywhere near as little space.

Let’s Wax Functional 02/27/2009


Published to Rick Minerich's Development Wonderland by Richard Minerich February 27, 2009 21:22

This week I have a very diverse set of topics:  First, using the functional programming concept of folds in C# to reimplement much of LINQ.  Then a bit of reflection on F# Grammar Parsers.  Finally, some community discussion on real world F# applications.

 

Blog – Matthew Podwysocki’s Functional C#, Fun With Folds

In this post Matthew reimplements much of LINQ using folds over IEnumerable.  This post is a great opportunity for those who are living in the C# world to see how some of the constructs in the functional programming world work.  I particularly like how Matt went the extra mile and included Pex tests for his examples.  It gives extra clarity to his already well defined extension methods.

 

Software – FParsec, A Parser Combinator Library for F#

The basic idea behind a Parser Combinator is that you use it to build a parser with a large vocabulary out of a set of single vocabulary sub parsers.  The claim is that, while this technique may not result in code that is as easy to read as something along the lines of fsyacc, it supports grammars which are much more complex while simultaneously allowing for an ultimately more extensible implementation.

I personally have not yet spent much time with either fsyacc or FParsec, but it’s interesting to contrast their different bottom up and top down approaches.  Fsyacc seems ideal for parsing simple grammars such as SQL.  The resulting code is very to understand and looks as though it would be similarly fast to write.  However, if you wanted to implement something along the lines of regular expressions, FParsec seems a much better choice due to it’s direct support of infinite look-ahead.

 

Stack Overflow – What areas of code are you using F# for?

A quick survey of Stack-Overflowers shows some uses cases for F# beyond DSL and Concurrency.  My personal favorites are statistical calculations and visualizations as they can be a nightmare to deal with in C#.  Also, as Talbott Crowell awed many with at the recent MSDN Boston conference, F# can be leveraged to easily make some amazing time-sensitive visualizations. 

I was also surprised that more people weren’t using F# for testing or scripting as they are also both very good use cases. 

 

A Note From Rick

I apologize for so frequently changing the name of my weekly roundup post.  Over the last few months it’s moved more and more in the direction of FP in .NET and so I felt “Discoveries this Week” was no longer appropriate.  Last week I decided to change the name but, after some reflection, it seems my choice was much too wordy.  I think I’ve finally found a name that fits.

How to determine which language(s) were used to build a .NET assembly


Published to Rick Minerich's Development Wonderland by Richard Minerich February 26, 2009 11:00

While in most cases there is no explicit information in an assembly as to which languages it was compiled from, it is possible to make an educated guess as to which languages were used.  This is due to the fact that each different .NET compiler leaves it’s own unique type of fingerprint.  In this article I discuss both my methodology for finding these fingerprints and which were unique to each language I used.

 

Methodology

For each language I made a new class library project.  I then reflected and compared each assembly to determine which unique characteristics it had.  It turned out that, at least for C#, F#, VB and C++, each was uniquely identifiable by the existence, or lack thereof, of certain features.

So to break it down a bit.

In each project I added one class and one public method in each of those classes:

  1: public class CSharpClass
  2: {
  3:     public void LocalMethod() {}
  4: }

After compiling each of these projects into it’s own assembly, I referenced them from another testing project.  To grab a set of features for each language, I used the following three reflection calls:

Assembly.GetTypes()
Assembly.GetCustomAttirbutes()
Module.GetFields( BindingFlags.NonPublic | BindingFlags.Static )

Then, with a simple program, I found which of these features were unique for each language.  This set of unique features ultimately represents a map of the imprint each compiler leaves.

 

F#

A compiled F# library will only have one attribute by default:

Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute

This made it the easiest to differentiate of all the languages I tested.  Even more interesting, this attribute contains three fields which specify the specific version of the F# compiler used to generate the assembly:

Major    1    int
Minor    9    int
Release    6    int

I’m always impressed with how the F# team consistently goes above and beyond when it comes to the small details.

 

Visual Basic

The Visual Basic assembly I generated was also easily identifiable via extra types which were automatically added:

My.MyApplication
My.MyComputer
My.MyProject
My.MyProject+MyWebServices
My.MyProject+ThreadSafeObjectProvider`1
My.Resources.Resource
My.MySettings
My.MySettingsProperty

As you can see from this list, the existence of these types in the “My” namespace is a fairly safe indicator that the Visual Basic language was used. 

 

C++ CLI / Managed C++

C++/CLI and Managed C++ are considered to be the same language with slightly different syntax as they share the same compiler.  However, there are four different compilation modes for C++ and each has somewhat different results.

  • /CLR – Common Language Runtime Support
  • /CLR:pure – Pure Common Language Runtime Support
  • /CLR:safe – Safe Common Language Runtime Support
  • /CLR:OldSyntax – Managed C++ Syntax

The /CLR, /CLR:pure and /CLR:OldSyntax settings provide easy to classify assemblies, as they all inject an enormous number of types (70+) into the assembly.  I verified that contained two types from the vc_attributes namespace:

vc_attributes.YesNoMaybe
vc_attributes.AccessType

However, /CLR:Safe is much different in that it injects no types and adds no assembly attributes by default.  The generated assembly was almost completely clean.  I was forced to use Reflector to determine how to differentiate this from C#.

 

C#

C# was one the most difficult to identify assembly type.  This is due to the fact that it has no unique types and only one unique attribute:

System.Reflection.AssemblyConfigurationAttribute

Unfortunately, this attribute is defined in the AssemblyInfo.cs file and so we can’t depend on it.  Up to this point it was only necessary to use two reflection calls:

Assembly.GetTypes()
Assembly.GetCustomAttirbutes()

I was hoping to keep things very simple.  However, to differentance these two languages it’s necessary to go a bit further.  It turns out that C++ always injects an module level field into the assembly while C# does not.  And so by using:

Module.GetFields(BindingFlags.NonPublic | BindingFlags.Static)

We can check for the existence of this kind of field and so differentiate these two types. 

After some investigation with reflector, I was able to find one particular feature unique to C#.  Unfortunately, it requires disassembling functions and looking at the resulting IL.  It seems as though a function definition never has a .maxstack of less than 8.  In all other languages I observed .maxstack had been set to values as low as 0 when defined in an empty function. 

However, as I am only currently concerned with these four languages, my testing on this matter has been very shallow and so pleae take it with a grain of salt.

 

Conclusion

I admit that my sample Assembly set was very small and my feature set very large.  However, while this type of classification may not be robust enough to be applicable to a system which depended on these results being absolutely true, I’ve shown that it is in fact entirely possible to make reasonably confident guesses as to the language used to generate a .NET assembly while using only simple reflection.  It would be interesting to see how well this holds for obfuscated assemblies as well as other “bare minimum” compilations generated via different combinations of compiler settings.

The next obvious step would be to extend what I have already written into a full Bayesian classifier.  Would be much better than a hardcoded hierarchy which would be fragile and possibly completely and repeatedly incorrect for some cases.  Another big advantage of using machine learning here, is that it would be easy to add new features and classification categories. 

Functional Discoveries in the Microsoft Sociocosm 02/20/2009


Published to Rick Minerich's Development Wonderland by Richard Minerich February 20, 2009 17:41

This week we have practical examples of Lazy Evaluation with Memoization, an interview with Don Syme and a discussion on the Visitor Pattern’s place in F#.  Also, any comments on the new title for my weekly posting would be appreciated.

 

Forum – Memoization and Lazy Evaluation in F# on HubFS

In this thread brianmcm (Brian McNamara) and divisortheory (???) explore using memorization and LazyLists to optimize a Trial Division driven prime generator.  It’s interesting to look at how their prime generator evolved over time as they incorporated these ideas and optimized.

 

Article – Kathryn Edwards interviews Don Syme on F# Development

In this technically light but still extremely interesting interview, Kathryn mainly directs the conversation in the direction of the development and adoption of the F# programming language.  The most interesting thing I gleaned from the interview?

One of the key designers of Haskell, Simon Peyton-Jones, is just down the corridor from me at Microsoft Research Cambridge and has been a great help with F#.

Perhaps my F#/Haskell genealogy graph needs an additional arrow.

 

Blog – Stephen Easey’s (?) Visitor Patten in C# and F#

In this post Stephen explores the Visitor Patten in both C# and F#.  I always love to see examples of how much more beautiful and concise F# is than C#.  The 218 line C# implementation shown beside the same implementation in 64 lines of F# makes for a great comparison in this regard. 

I agree with Stephen’s conclusion in that, given the purpose of the visitor pattern is to separate algorithm from object via a double dispatch layer, in many situations the visitor pattern is unnecessary in F# because of its advanced pattern matching capabilities.

However, I feel that he may not have considered the perspective of an API provider.  In this context, it may be desirable for the consumer of an API to be able to extend the dispatch process to handle new cases.  The issue with a single monolithic matching function is that all of the logic is contained within that single function and so the system is no longer nearly as open to extension.  This violation of the Open Closed Principle (which applies to building APIs in any type of language) will make for difficult to reuse software. 

Perhaps a F# pattern matching equivalent could be made with lambda functions for each branch.  Lambdas could be curried into the matching function and so each branch could potentially be replaced with new logic by the consumer.  However, this is feels to me like reimplementing OO with FP constructs.

Discoveries This Week 02/13/2009


Published to Rick Minerich's Development Wonderland by Richard Minerich February 13, 2009 15:43

A wide range of subjects this week including testing, concurrent performance, exception handing and data structures.

 

Software – FsStory, a library for writing executable user stories in F#

I feel that F#, with it’s concise syntax, is an ideal framework for writing tests.  Combined with FsStory F# is made much more powerful in this regard as it becomes possible to write user case tests and have them read very much like simple English.   F# has a huge advantage here over C# as it has much less syntactic cruft and so much less for your brain to process while reading.   For example:

  1: [<Fact>]
  2: let MoveTurtleToPosition() = 
  3:        given ATurtle
  4:     |> andGiven IsRotated90DegreesToTheRight
  5:     |> whens (TurtleWalksSteps 9)
  6:     |> thens (TurtleIsLocatedAt (0,9))   
  7:     |> endStory

It’s obvious exactly what this is testing and how.  Yet, it takes very little time to read.  Very impressive.

 

Blog –Jan Varwig’s F# Observations

While this post is rather old, I was very excited by Jan’s analysis of an article on comparing C# and F# using the distributed .NET computing framework Alchemi

Optimizing this application showed that F# would finish in 1.5 seconds while C# would not complete any faster than 2.6 seconds.

It’s important to note that these results are a year old now and that with newer F# optimization the results might be even better.

The other interesting thing in this post is the discussion of the cost of heavyweight threads on the CLR.  Which is directly related to our next discovery:

 

Blog – Daniel Moth’s New and Improved CLR 4 Thread Pool Engine

A first glimpse of that is in store for us in the next iterating of the Thread Pool.  Not surprisingly, the optimizations seem to focus on sharing work across multiple threads. 

With F#’s thread-friendly nature and new the optimized thread pool, I'm very excited to see how .NET compares to other grid computing platforms after it’s 4.0 release.

 

Blog – Arthur Herczeg’s F# Exceptions

An informational post on managing and throwing both F# native and general .NET exceptions in F#.  Included are examples of imperative style try, catch and try, finally patterns.

 

Blog – Karl Krukow’s Understanding Clojure’s PersistentVector

Rich Hickey, the father of the Clojure language, has gone out of his way to optimize Clojure’s structures for data sharing with immutability.  I was very impressed with Clojure when, back last march, Rich Hickey came to Northampton and presented it in a talk.  While, Clojure runs on the JVM and so comes along with all of the baggage that it entails, it’s a fantastic language and people in the java community are flocking to it.

I would love to see some of these data structures ported to the .NET framework so that F# could take advantage of them.  As far as I am currently aware, F# data structures are instead implemented via binary trees and so are much less efficient in terms of the amount of data shared.

One of these languages is not like the others - Part 1 - Enforcement of Abstract Implementation


Published to Rick Minerich's Development Wonderland by Richard Minerich February 10, 2009 15:47

This is the first in a series of posts on the topic of interaction between different .NET languages.  I will cover all of the major Microsoft languages: C#, Visual Basic, F# and C++/CLI.

In this first post in the series I will build a four language project in Visual Studio 2008 and begin to explore inter-language inheritance.  One of the languages behaves in a significantly different way when compared with the others, can you guess which one it is?

 

Enforcement of Abstract Implementation

First things first, let’s define our abstract base class.  C# is considered the standard language for library architecting and so it is what we will be using.

  1: public abstract class CSharpBaseClass
  2: {
  3:   public abstract void PublicAbstractMethod();      
  4:   public abstract void PublicAbstractMethod(int inint);
  5:   protected abstract void ProtectedAbstractMethod();
  6:   protected abstract void ProtectedAbstractMethod(int inint);
  7: }

 

In each of our child projects we will be inheriting from this class.  Let’s start with C#.

  1: public class CSharpChildClass : CSharpBaseClass
  2: {
  3: }

Now anyone with even a bit of experience in the C# language knows that this won’t compile.  For each of the abstract methods in the base class the inheriting class is expected to provide an implementation.

… error CS0534: 'CSharpChild.CSharpChildClass' does not implement inherited abstract member …

 

This is similarly true for Visual Basic.

  1: Public Class VBChildClass
  2:   Inherits CSharpBase.CSharpBaseClass
  3: End Class

 

… error BC30610: Class 'VBChildClass' must either be declared 'MustInherit' or override the following inherited 'MustOverride' member(s):

 

F# shares this behavior as well.

  1: type FSharpChildClass() =
  2:   inherit CSharpBase.CSharpBaseClass()

    … error FS0191: No implementation was given for 'CSharpBaseClass.PublicAbstractMethod() : unit'.

Kudos to the F# compiler designers for the verbose compile time errors.

    error FS0054: This type is 'abstract' since some abstract members have not been given an implementation. If this is intentional then add the '[<AbstractClass>]' attribute to your type.

 

However, C++/CLI does not.  It’s perfectly acceptable to inherit from an abstract class and provide no implementation for it’s abstract members.

  1: public ref class CppChildClass : public CSharpBaseClass
  2: {
  3: };

While a warning is issued, it seems insufficient for what has just taken place:

… warning C4570: 'CppChild::CppChildClass' : is not explicitly declared as abstract but has abstract functions

The result is that the class in question is defaulted to abstract.  If someone where to attempt to instantiate it downstream, it would cause a compiler error:

  1: CppChildClass cpp = new CppChildClass();
  2: cpp.LocalMethod();

error CS0144: Cannot create an instance of the abstract class or interface 'ManagedCppChild.ManagedCppChildClass'

This is bad because, if you were an API developer and so did not consume all of your objects, it would be possible to ship a version of your product with abstract suddenly toggled on for one or more of your classes.  All it would take would be for a developer to add a new inherited class or member to an existing abstract base class without writing a corresponding test for every abstract member or inheriting class.

 

Conclusion

So, what can we learn from this?  It seem that when using C++/CLI (or managed C++) it is not sufficient to depend on abstract classes to enforce that members are implemented.  Testing must also be strictly enforced.

One of these languages is not like the others - Part 1 - Enforcement of Abstract Implementation


Published to Rick Minerich's Development Wonderland by Richard Minerich February 10, 2009 15:47

This is the first in a series of posts on the topic of interaction between different .NET languages.  I will cover all of the major Microsoft languages: C#, Visual Basic, F# and C++/CLI.

In this first post in the series I will build a four language project in Visual Studio 2008 and begin to explore inter-language inheritance.  One of the languages behaves in a significantly different way when compared with the others, can you guess which one it is?

 

Enforcement of Abstract Implementation

First things first, let’s define our abstract base class.  C# is considered the standard language for library architecting and so it is what we will be using.

  1: public abstract class CSharpBaseClass
  2: {
  3:   public abstract void PublicAbstractMethod();      
  4:   public abstract void PublicAbstractMethod(int inint);
  5:   protected abstract void ProtectedAbstractMethod();
  6:   protected abstract void ProtectedAbstractMethod(int inint);
  7: }

 

In each of our child projects we will be inheriting from this class.  Let’s start with C#.

  1: public class CSharpChildClass : CSharpBaseClass
  2: {
  3: }

Now anyone with even a bit of experience in the C# language knows that this won’t compile.  For each of the abstract methods in the base class the inheriting class is expected to provide an implementation.

… error CS0534: 'CSharpChild.CSharpChildClass' does not implement inherited abstract member …

 

This is similarly true for Visual Basic.

  1: Public Class VBChildClass
  2:   Inherits CSharpBase.CSharpBaseClass
  3: End Class

 

… error BC30610: Class 'VBChildClass' must either be declared 'MustInherit' or override the following inherited 'MustOverride' member(s):

 

F# shares this behavior as well.

  1: type FSharpChildClass() =
  2:   inherit CSharpBase.CSharpBaseClass()

    … error FS0191: No implementation was given for 'CSharpBaseClass.PublicAbstractMethod() : unit'.

Kudos to the F# compiler designers for the verbose compile time errors.

    error FS0054: This type is 'abstract' since some abstract members have not been given an implementation. If this is intentional then add the '[<AbstractClass>]' attribute to your type.

 

However, C++/CLI does not.  It’s perfectly acceptable to inherit from an abstract class and provide no implementation for it’s abstract members.

  1: public ref class CppChildClass : public CSharpBaseClass
  2: {
  3: };

While a warning is issued, it seems insufficient for what has just taken place:

… warning C4570: 'CppChild::CppChildClass' : is not explicitly declared as abstract but has abstract functions

The result is that the class in question is defaulted to abstract.  If someone where to attempt to instantiate it downstream, it would cause a compiler error:

  1: CppChildClass cpp = new CppChildClass();
  2: cpp.LocalMethod();

error CS0144: Cannot create an instance of the abstract class or interface 'ManagedCppChild.ManagedCppChildClass'

This is bad because, if you were an API developer and so did not consume all of your objects, it would be possible to ship a version of your product with abstract suddenly toggled on for one or more of your classes.  All it would take would be for a developer to add a new inherited class or member to an existing abstract base class without writing a corresponding test for every abstract member or inheriting class.

 

Conclusion

So, what can we learn from this?  It seem that when using C++/CLI (or managed C++) it is not sufficient to depend on abstract classes to enforce that members are implemented.  Testing must also be strictly enforced.