brainbaking/content/wiki/code/csharp/classes.md

6.4 KiB

+++ title = "classes" draft = false tags = [ "code", "csharp", "classes" ] date = "2014-01-29" +++

Classes

Dynamically creating instances

Gebruik Activator:

Activator.CreateInstance(type) as MyType

Overrides en shadowing: 'new' en 'virtual'

Zie onder andere:

  1. http://stackoverflow.com/questions/1014295/new-keyword-in-method-signature
  2. http://stackoverflow.com/questions/9892468/java-is-there-java-equivalent-for-c-sharp-new-keyword-in-method-signature-how

In java zijn alle methods virtual, dat wil zeggen dat ze overschrijfbaar zijn (@Override) zodat de method in de diepst geneste polymorfe structuur gebruikt wordt. In C# is daarvoor het keyword virtual nodig:

public class A
{
   public virtual void One();
   public void Two();
}

public class B : A
{
   public override void One();
   public new void Two();
}

B b = new B();
A a = b as A;

a.One(); // Calls implementation in B
a.Two(); // Calls implementation in A
b.One(); // Calls implementation in B
b.Two(); // Calls implementation in B

De concretere klasse moet dan overriden met override dat niet gaat als het niet virtual is (je kan ook niet overerven waarbij een klasse sealed is, zoals final in java). Wat hier wel opmerkelijk is, is het gebruik van het keyword new in de tweede method "Two". Hierbij kan je de eerste implementatie toch nog hiden, maar je moet wel upcasten! Misschien is dit nog handig bij het schrijven van legacy testen?

Het is in java niet mogelijk om een final method te overriden. (Private telt natuurlijk niet mee...) In C# is het wel mogelijk om halverwege de chain te sealen!

Closures en Lambda's

Interessante links:

  1. Lambda expressions MSDN C# programming guide
  2. Expression Trees MSDN hier worden lambda's gebruikt voor LINQ

Passing on 'work' to a method, to execute the lambda

In Java:

public interface Workable<T> {
  public T work();
}

public class MyWork extends Workable<MyObj> {
  public MyObj work() {
    // do stuff here 
  } 
}

public class Executer {
  public <T> T doStuff(Workable<T> w) {
     prepare();
     T result = w.work();
     cleanup();
  }

  public MyObj createMyObj() {
    return doStuff(new MyWork());
  }
}

Basically, gebruik interfaces. Pijnlijk en verbose. In C# kan je () => gebruiken om een anonieme method aan te maken, en Func<> als type gebruiken.

Concreet voorbeeld:

        internal virtual T Execute<T>(Func<T> work)
        {
            Connection.Open();
            var transaction = Connection.BeginTransaction();
            try
            {
                var retVal = work.Invoke();
                transaction.Commit();
                return retVal;
            }
            catch (Exception)
            {
                transaction.Rollback();
                throw;
            }
            finally
            {
                Connection.Close();
            }
        }
        
        public bool BlaBla()
        {
          return Execute(() =>
          {
              // do query stuff in here.
              return true;
          });
        }
Q: Wat is het verschil tussen een Lambda (>()) en een delegate?

A: niets; zie voorbeeld:

Func<string, int> giveLength = delegate(string text) { return text.Length; };
Func<string, int> giveLength ###### (text > text.length);

de => notatie is nieuwer.

Q: Wat is het verschil tussen een expression type en een anonymous type?

http://stackoverflow.com/questions/299703/delegate-keyword-vs-lambda-notation

If you assign the lambda to a delegate type (such as Func or Action) you'll get an anonymous delegate. If you assign the lambda to an Expression type, you'll get an expression tree instead of a anonymous delegate. The expression tree can then be compiled to an anonymous delegate. Edit: Here's some links for Expressions.

Zeer interessant artikel: http://weblogs.asp.net/scottgu/archive/2007/04/08/new-orcas-language-feature-lambda-expressions.aspx

############ Nested (inner) classes in C# ############

http://blogs.msdn.com/b/oldnewthing/archive/2006/08/01/685248.aspx - C# heeft geen referentie naar de outer class ($0 die in Java er impliciet is), bijgevolg moet je dit zelf bijhouden.

Zie ook http://stackoverflow.com/questions/4770180/anonymous-inner-classes-in-c-sharp

############ Modules as anonymous inner classes, JavaScript pattern ############

var Mod = (function(consoleDep) {
	
	function yo() {
		consoleDep.log("yo");
	}

	return {
		hi: yo
	};

})(console);

Mod.hi();

equals

        private interface ILoggable
        {
            void Log(string msg);
        }

        private class Console : ILoggable
        {
            public void Log(string msg)
            {
                Debug.WriteLine(msg);
            }
        }

        [TestMethod]
        public void TestMe()
        {
            var Mod ###### new Func<ILoggable, Dictionary<string, Action>>((consoleDep) >
                {
                    Action yo ###### () > consoleDep.Log("yo");

                    return new Dictionary<string, Action>
                        {
                            { "hi", yo }
                        };
                })(new Console());
            Mod["hi"]();
        }

Problemen

  • cannot assign lambda expression to an implicitly-typed local variable (var bij de yo ipv Action)
  • duck typing for module dependencies??

############= Enums in C# ############=

Zie ook http://stackoverflow.com/questions/469287/c-sharp-vs-java-enum-for-those-new-to-c

Enumerations in the CLR are simply named constants. The underlying type must be integral. In Java an enumeration is more like a named instance of a type. That type can be quite complex and - as your example shows - contain multiple fields of various types.

Optie 1: gebruik extensions (nog altijd een switch nodig omdat het type in algemene vorm binnen komt)

Optie 2: maak uw eigen enum klasse door immutable readonly classes te maken:

class Planet
{
  public static readonly Planet EARTH = new Planet("earth");

  private string name;
  private Planet(string name)
  {
    this.name = name;
  }
  
  public static IEnumerable<Planet> Values
  {
    // return set of planets
  }
}