Apr 30, 2009

Reflection performance

int x = 10;
Assembly a = Assembly.Load("mscorlib");

Type t1 = typeof(int);
Type t2 = x.GetType();
Type t3 = a.GetType("System.Int32");
Type t4 = Type.GetType("System.Int32");

Console.WriteLine(t1 == t2);
Console.WriteLine(t2 == t3);

Console.WriteLine(t3 == t4);

All of the equality comparisons will evaluate to true and, assuming that Type's Equals method is transitive (as all Equals implementations are supposed to be), then we can infer that t1 == t2 == t3 == t4. Loading t1 is the most efficient, t2 is a close second, and t3 and t4 are horribly inefficient. t3 is slightly more efficient because it only searches mscorlib.dll, whereas t4 searches all loaded assemblies. In fact, in a little test program I wrote, t2 is twice as slow as t1, t3 is 100 times slower than t2, and t4 is twice as slow as t3.

Apr 28, 2009

How many chinese characters can a computer display?

Recently there is news Name Not on Our List? Change It, China Says? Some people think of it from a perspective of culture, philosophy, or politics. But I a software engineer, let's talk about it from perspective of computer science.

When we say put your name in computer, what does it means? Let's say your name is "a", it will be converted a number 97 by the computer, this number is represented in a serial of bits (0 or 1). This process is called encoding. But the text you see, is not a number, why? Because computer convert the number into a picture, we call it decoding? The most poplular encoding format today, it is unicode. It uses 16bit to store all the charactors(no matter it is english letter, or chinese charactor, greek, let's just call them charactors at this moment). 16 bit means 65536 possibilities of combination, which means the system can only accommodate 65536 character. As I know the unicode system is still evolving, so it actually can accommodate more than 65536. But the fact is it can only handles limited number of character. In unicode system, the English letter 'a' is converted to number 97. And the Chinese character 'δΈ€' (one) is converted to 19968. Lets say, I have a new baby, I want to give it a Chinese name, I look up a ancient Chinese dictionary, the dictionary was created long before modern computer was invented. And I found a character in the dictionary, which is not our encoding system for example unicode. So there is no way to input the name into existing computer system. What option do we have? We can either update encoding system to encode your name. We need to create a number, and create a picture, and associate the number with the picture. And we also need to distribute the encoding system to all the computers? Obviously, it is not an easy job. The easy solution is to pick your name from the characters in the existing encoding system, for example unicode, but not from an ancient Chinese dictonary or even invent a Chinese character which never exists. That is what the Chinese government is try to do. Actually, unicode already can display more than 20944 Chinese character, even the most knowledgeable Sinologist can use. There are surely some people who will be affected, but 1.3 billion chinese, it is not that significant. Click here to see a list chinese character in unicode ranged from 19968 to 40911.

Apr 27, 2009

divitus classitus

In the book of CSS Mastery: Advanced Web Standards Solutions, there is a section about divitus and classitus.

Using too many divs is often described as divitus and is usually a sign that your code is poorly structured and overly complicated. Some people new to CSS will try to replicate their old table structure using divs. But this is just swapping one set of extraneous tags for another. Instead, divs should be used to group related items based on their meaning or function rather than their presentation or layout.

The root reason of this phenomenon is that designer tend to rush to see the result first, and forget the semantic of the content(the markup) express. My experience is that the a clean markup with strong semantic is a good document. A good document is starting point of good design. A good design is easy to be restyled and extended. Most of visual style can be implemented by CSS of current version. If it can not satisfying your requirements, we can wait for next generation (CSS 3 or CSS 4?). But before they are available, we can use javascript implement your advanced design needs. But the bottom line is to forget about style, when you authorize your markup, and always remember make your markup semantic, which means your document is still understandable even it is opened in notepad or lynx.

Semantic and style , they are different concern. While some developers and visual designer understand the rule of separation of concern, but web technology (like asp.net server controls, Web form) tend to make people deviate from it. Although it is not the fault of these technology, in fact, you can use these technology to achieve very semantic markup, but they tend to lure people to mix them together. ASP.NET MVC is trying to fix this.

Below is example of divitus classitus.



Here is restructure markup

Login

First time here? Forgot your password?

Apr 15, 2009

Object vs Function


Object.prototype.sayhi = function() { alert("hi"); }

var o = {};
alert(o.constructor); //function Object(){[native code]}, created by function Object()
alert(Object.prototype); //[object Object], ultimate prototype
o.sayhi(); //show hi

Function.prototype.saybye = function() { alert("bye"); }


alert(f.constructor); //function Function(){[native code]}, created by function Fuction()
alert(Function.prototype); //function prototype{[native code]},
//I think Function.prototype still link to an object constant {},
//so that it can be route to  [object Object], the ultimate prototype

alert(Function.prototype.constructor); //function Function(){[native code]}, created by function Fuction()
alert(f.prototype); //[object Object], ultimate prototype


function f() { }
f.sayhi(); //show hi
f.saybye(); //show bye


    alert(document.constructor); //[objectHTMLDocument
    alert(document.constructor.prototype); //[Interface prototype object]
    alert(document.constructor.prototype.constructor); //null in IE, function Object() in firefox
  

Apr 14, 2009

delete

The delete operator can be used to remove a property from an object. It will remove a property from the object if it has one. It will not touch any of the objects in the prototype linkage. Removing a property from an object may allow a property from the prototype linkage to shine through:
var stooge = {};
stooge.name = "fred";

if (typeof Object.beget !== 'function') {
    Object.beget = function(o) {
        var F = function() { };
        F.prototype = o;
        return new F();
    };
}
var another_stooge = Object.beget(stooge);
another_stooge.name = "jeff";
alert(another_stooge.name); //jeff
delete another_stooge.name;
alert(another_stooge.name); //fred


|| , && and !!

&& is guard operator aka "logical and", and || is default operator "aka logical or", we normally see the code like the following

if ( condtion1 && condition2) { }
if (condition1 || condition2) { }

&& is also know as guard operator. If first operand is truthy, the result is second operand, else result is is first operand. It can be used to avoid null reference.

if (a){
  return a.memeber;
} else {
   return a;
}
//this is the same
return a && a.member

|| is aslo know is default operator. It is the opposite of && . If first operand is truethy, then result is first operand, else result is second operand. It can be used to fill in default value like the following, it is like ?? in csharp


var last = input || {}; //{} is default value

The !! operator can turn all value into boolean value, you can think of it boolean conversion operator. Keep in mind that truthy/falsy value is not boolean value. For example "hello" is truthy value. So you can write code like


if ("hello")
{
   alert("hello");
}

But "hello" itself is not boolean value, if you want to convert it into boolean value, you need to write


function toBoolean(v)
{
   if (v)
   {
     return true;
   }
   else
   {
      return false;
   }
}

var b = "hello";
alert(toBoolean(b));

//or you can just write
alert(!!b);

Apr 13, 2009

Apr 12, 2009

context of setTimeout and eval

setTimeout is a method of window object. "this" context refer to the window. But you can change its context in the following way. setTimeout does not support call method.
setTimeout(function() { alert(this); }, 0); //window
//setTimeout.call({}, function() { alert(this); }, 0); //not supported
setTimeout((function() { alert(this); }).call({}), 0); //object 
eval is also a method of Global object, in the case of browse, this is window object. But is context defined by its Containing context. Eval also does not support call method

function Foo() {
    this.TestContext = function() {
        eval("alert(this==window);"); //show false
        setTimeout(function() { alert(this == window); }, 0);  //show true
    }
}

var f = new Foo();
f.TestContext(); 

eval("alert(this);");
eval.call({}, "alert(this);"); 
//firefox does not support this, but IE support, but it does not change context

Anonymous function's contexgt

var name = "window";
    var f = (function() { alert(this.name); });
    f(); //window
    f.name = "local";
    f();     //still window, the function still run in the context of window
    f.call(f); //local

    var p = { name: "local" };
    p.f = f;
    p.f(); //local
    f.call(p); //local


(function() { alert(this); })(); 
//the defining context is window, it will output window

(function() { alert(this); }).call({}); 
//the defining context is window, but call switch the context

== vs ===

Here is the msdn documentation

Equality (==, !=)

  • If the types of the two expressions are different, attempt to convert them to string, number, or Boolean.
  • NaN is not equal to anything including itself.
  • Negative zero equals positive zero.
  • null equals both null and undefined.
  • Values are considered equal if they are identical strings, numerically equivalent numbers, the same object, identical Boolean values, or (if different types) they can be coerced into one of these situations.
  • Every other comparison is considered unequal.

Identity (===, !==)

These operators behave identically to the equality operators except no type conversion is done, and the types must be the same to be considered equal.

Here is some test case writing in Qunit.

test("Equality test", function() {
    ok(1 == 1 && 'a' == 'a' && 1 == '1' && 0 == false && '' == false);
    ok(null == null, "null equals to null");
    ok(null == undefined, "null equals undefined");
    ok(undefined == undefined, "undefined equals undefined");
    ok({} != {}, "different objects are unequal");
});

test("Identity test", function() {
    ok(1 !== "1" && null !== undefined, "must be the same type, not conversion");
});

If you want writing a "if (condition)" statement, you should use identity compare, and you can also default boolean conversion in javascript. You can write "if (variable_name)" or "if (variable_name)". Javascript treat false, null, undefined, "" (emtpy string), 0, NaN as falsy value, all other values are truthy, including "0", and "false". If you want to explicitly to convert a variable into boolean type, you can use !!variable_name statement, but you shouldn't use "if (!!variable_name) " statement. Here is some example

Apr 4, 2009

Overflow

This property is used to control the behavior of container in which its content expend over its content area. It is not used to control the behavior of container of the container of the content. Normally overflow will not happen because the container of content can expend vertically or horizontally. For text content is non-replaced elements, overflow horizontally will not happen because it can be wrapped into next line. But overflow overcritical y is possible. But for Replaced Elements it can overflow horizontally.

Horizontal Formating of block element

The "seven properties" of horizontal formatting are: margin-left, border-left, padding-left, width, padding-right, border-right, and margin-right. Padding and margin is set to 0 by default. Width is set to auto. This means the block element will try expend as much as possible into its containing content space. /p>

If width is auto, whether margin-left and margin-right is set to auto or just 0 has not effect. Because either way, their computed value will be the same 0. But if width is has a value, and margine-left and margin-right is set to auto, then that margin will expand or contracted automatically. If both margin is set to auto, and the width has a value, the the content of the block will be set to horizonal center.

The Containing Block

Every element is laid out with respect to its containing block; in a very real way, the containing block is the "layout context" for an element.For an element in the normal, Western-style flow of text, the containing block is formed by the content edge of the nearest block-level, table cell, or inline-block ancestor box. You don't need to worry about inline elements since the way they are laid out doesn't depend directly on containing blocks.

vertical-align

In CSS, the vertical-align property applies only to inline elements and replaced elements such as images and form inputs. vertical-align is not an inherited property. It can be one of baseline | sub | super | top | text-top | middle | bottom | text-bottom | | | inherit. The initial value is baseline.

line-height

The line-height property refers to the distance between the baselines of lines of text rather than the size of the font, and it determines the amount by which the height of each element's box is increased or decreased. In the most basic cases, specifying line-height is a way to increase (or decrease) the vertical space between lines of text, but this is a misleadingly simple way of looking at how line-height works. line-height controls the leading, which is the extra space between lines of text above and beyond the font's size. In other words, the difference between the value of line-height and the size of the font is the leading.

When applied to a block-level element, line-height defines the minimum distance between text baselines within that element. Note that it defines a minimum, not an absolute value, and baselines of text can wind up being pushed further apart than the value of line-height

Every element in a line of text generates a content area, which is determined by the size of the font. This content area in turn generates an inline box that is, in the absence of any other factors, exactly equal to the content area. The leading generated by line-height is one of the factors that increases or decreases the height of each inline box.

To determine the leading for a given element, simply subtract the computed value of font-size from the computed value of line-height. That value is the total amount of leading. And remember, it can be a negative number. The leading is then divided in half, and each half-leading is applied to the top and bottom of the content area. The result is the inline box for that element.

As an example, let's say the font-size (and therefore the content area) is 14 pixels tall, and the line-height is computed to 18 pixels. The difference (four pixels) is divided in half, and each half is applied to the top and bottom of the content area. This creates an inline box that is 18 pixels tall, with 2 extra pixels above and below the content area. This sounds like a roundabout way to describe how line-height works, but there are excellent reasons for the description.

When the line-height is inherited by one block-level element from another, things get a bit trickier. line-height values inherit from the parent element as computed from the parent, not the child. It probably wasn't what the author had in mind:

body {font-size: 10px;}
div {line-height: 1em;}  /* computes to '10px' */
p {font-size: 18px;}

This paragraph's 'font-size' is 18px, but the inherited 'line-height' value is only 10px. This may cause the lines of text to overlap each other by a small amount.

A solution is, instead using em, or percentage (%), simply use a number with out any unit symbol

div {line-height: 1.5;}
p {font-size: 18px;}

This paragraph's 'font-size' is 18px, and since the 'line-height' set for the parent div is 1.5, the 'line-height' for this paragraph is 27px (18 * 1.5).

inherit

There is one keyword that is shared by all properties in CSS2.1: inherit. inherit makes the value of a property the same as the value of its parent element. In most cases, you don't need to specify inheritance, since most properties inherit naturally; however, inherit can still be very useful.

For example, consider the following styles and markup:

#toolbar {background: blue; color: white;}

One | Two | Three

The div itself will have a blue background and a white foreground, but the links will be styled according to the browser's preference settings. They'll most likely end up as blue text on a blue background, with white vertical bars between them.

You could write a rule that explicitly sets the links in the "toolbar" to be white, but you can make things a little more robust by using inherit. You simply add the following rule to the style sheet:

#toolbar a {color: inherit;}

This will cause the links to use the inherited value of color in place of the user agent's default styles. Ordinarily, directly assigned styles override inherited styles, but inherit can reverse that behavior.

Pixel in CSS

CSS2 recommended 90ppi as the reference pixel, but CSS2.1 recommends 96ppia measurement common to Windows machines and adopted by modern Macintosh browsers such as Safari. This means when I display 96 pixel in my screen, it should be 1 inch length in physics. But if my screen is about 110ppi, so 1 inch in css is going to less than 1 inch in my scree. But how about printer, it normally print 600ppi. It actually first convert pixel in screen to inch in scree, then print the length in inch in printer, and print the pixel by timing 600ppi to length in inch.

Unit in css

All length units can be expressed as either positive or negative numbers followed by a label (although some properties will accept only positive numbers). You can also use real numbersthat is, numbers with decimal fractions, such as 10.5 or 4.561. All length units are followed by a two-letter abbreviation that represents the actual unit of length being specified, such as in (inches) or pt (points). The only exception to this rule is a length of 0 (zero), which need not be followed by a unit.

Make IE more css2.1 compliant

Check here