Bill Blogs in C#

Bill Wagner discusses C#, LINQ, and other items of interest

January 2006 - Posts

What if your content disagreed with Google's agenda

These two queries show the incredibly control Google has over ability to find information.

The first link shows what we outside of China can find. The second shows what can be found inside China.

Google has been (rightly) chastised for censoring content in response to complaints from the Chinese government, so I won't simply repeat those arguments. (I do agree with them, in case you were wondering). But, imagine if Google censored its results based on corporate interests, or the executives' political interest...   That's chilling.



The query we can see
Complete with lots of tanks
What's available inside mainland China
Shiny, Happy, people

Posted by wwagner | with no comments
Filed under:
So you think you want to see the Superbowl

A friend pointed out this link about driving in Detroit for those of you coming into town for the superbowl.

My two favorites:

"The minimum acceptable speed on I-696 and I-275 is 85, regardless of the posted speeds.  Anything less is considered downright SISSY. Oh, and don't even think of allowing more than one car length between cars!"

"If you are in the left lane, and only going 70 in a 60 mph zone, people are not waving because they are so friendly in Detroit. I would suggest you duck."

I'll add a couple observations of my own:

. In Detroit, speed limits aren't really an absolute, it's more of a reference point. Doing 70 mph in a 70 mph zone means "I'm really freakin' late now."

. The official driver's motto in Detroit:  "We built em, we know how fast they'll go."



Detroit Driving Tips for Superbowl Guests
Somewhat True, some over the top
Posted by wwagner | with no comments
Or, how many analogies does it take to make a point?

Yet again, a discussion of different programming languages for .NET, and now folks are blogging on the same topic. See Rocky Lhotka, Patrick Hynds, and Scott Hanselman.

Patrick Hynds starting by saying this (related to VB.NET and C#):

I know when to use a Tank (plodding and durable lethality) and I know when to use a A-10 (fast, maneuverable and vulnerable lethality), but if you make tanks fly and add a few feet of armor on an A-10 then you get the same muddy water we have between C# and VB.Net. Those that know me will forgive the military analogy ;)

That’s enough to get others started. Rocky Lhotka responds:

The problem we have today, in my opinion, is that C# is a flying tank and VB is a heavily armored attack plane.

And Scott Hanselman adds:

“Personally at this point, I don't see a reason for us to have two languages other than we always have. It started with C++/MFC versus VB1/2/3 in the early 90s and we'll never come back together. Some folks think that this is good because humans crave choice. Others think it's just wasting time and effort as we design language and development tools twice.”

I think he’s close, but I think there’s a better analogy: Shinichi Suzuki’s journey toward his method for teaching music to young children. (I heard this story from my daughter’s first violin teacher: Edmund Sprunger,  who studied with Suzuki). When Suzuki was a performing musician, he had to learn other languages to manage while traveling (German, English, French, etc). His initial impression was that it was very difficult to learn these languages, and he assumed that it would be very difficult for children in these other countries to learn those difficult languages. Therefore, he reasoned, children in those countries must begin speaking at a much older age than Japanese children. As he traveled, we marveled that children in these other countries could speak their native tongue as easily as Japanese children spoke Japanese. Also, he was amazed as how difficult it was for these children to understand or begin speaking Japanese when he spoke it to them: his preconception was that Japanese would be easy to learn.

Well, in the end, he realized that children responded best to whatever language they learned first. It was easy to understand whatever language their parents used speaking to them. (By the way, that was his justification for starting his music program: It would give all people everywhere a common language, that of music).

The point of this little side-trip is that it is human nature to feel most comfortable in the language that they first used. For software developers, that means you will feel most comfortable in the language you used first (unless you’ve been using a different language for an incredibly long time.)

That leads me to two conclusions:

First, the VB vs. Curly Braces debate just won’t go away. There are too many ‘native speakers’ in each tongue. It’s like debating whether Japanese or English is easier: The answer depends on your perspective and which language you feel more comfortable using. This extends beyond simple language constructs. It extends to library features like the “My” namespace in VB.NET. It extends to IDE features like Refactoring in C#.

Second, this speaks incredibly well for the future of LINQ. LINQ introduces functional programming styles to a whole new group of people. In fact, three groups. C#, and VB.NET developers can use VB.NET with functional idioms, without leaving the familiarity of their regular language. And, for those aging Computer Science majors that had some LISP in school, but haven’t used it since, you can use those idioms without remembering different libraries, other syntax, implicitly converting from the language you normally use to LISP dialects.

It’s an interesting future.



Posted by wwagner | with no comments
Filed under:
The one where I discuss Object and Collection Initializers

This entry continues my journey through the LINQ samples that get delivered with the LINQ CTPs. (Part 1 is here.).

The second sample (Linq2) shows another where clause:

public void Linq2()
{

  List<Product> products
    = GetProductList();


  var soldOutProducts =

    from p in products

    where p.UnitsInStock == 0

    select p;


  Console.WriteLine("Sold out products:");

  foreach (var product in soldOutProducts)
  {

    Console.WriteLine("{0} is sold out!", product.ProductName);

  }

}

There are only a couple new things to learn in this method. First, var is not limited to collections of built-in types. soldOutProducts has the compile-time type of IEnumerable<Product>, and the runtime type of Where<Product>.

The GetProductList method also has some interesting new C# syntax. The GetProductList() calls an internal method named buildLists(). buildLists() shows how a new pseudo-constructor syntax, called Object Initializers, and Collection Initializers. (See section 26.4 in the C# 3.0 specification if you want the official definition.)

private void createLists()
{

  // Product data created in-memory using collection

  // initializer:

  productList = new List<Product>
  {

    { ProductID = 1, ProductName = "Chai",

      Category = "Beverages", 
      UnitPrice = 18.0000M,

      UnitsInStock = 39 },

    { ProductID = 2, ProductName = "Chang",

      Category = "Beverages", UnitPrice = 19.0000M,

      UnitsInStock = 17 },

    { ProductID = 3, ProductName = "Aniseed Syrup",

      Category = "Condiments", UnitPrice = 10.0000M,

      UnitsInStock = 13 },


    // lots elided.


  };

}

The outer {, } is a collection initializer. Each item in the comma separated list specifies one object that should be added to the list. (The portion of the list above could be replaced by the equivalent calls to productList.Add() ).

The object initializer syntax is consistent with the language syntax used to set properties on Attributes: You specify the property (or field) name, and the value. You can specify values for as many of the properties as you want, with the limitation that you can set each property no more than once.

There is another bit of compiler magic going on in the createLists method shown above. This expression:

{ ProductID = 1, ProductName = "Chai",
  Category = "Beverages", UnitPrice = 18.0000M,

  UnitsInStock = 39 },

is the same as this:

new Product { ProductID = 1, ProductName = "Chai",
  Category = "Beverages", UnitPrice = 18.0000M,

  UnitsInStock = 39 },

The entire expression is the same as this:

Product __p = new Product();
__p.ProductID = 1;

__p.ProductName = "Chai";

__p.Category = "Beverages";

__p.UnitPrice = 18.0000M;

__p.UnitsInStock = 39;

productList.Add( __p );

Because of the context, creating the product in the initializer for the List<Product> collection, the compiler infers the type of the object to create. If you’re beginning to get the idea that type inference is a big thing in C# 3.0, you’re right. But, remember that type inference is not the same as untyped languages like java script. The compiler knows what type to create, and if your expression does not follow those rules, you’ll get the expected compiler errors.

Object Initializers and embedded value types have some limitations. Suppose I had a class type where one of the embedded members was a Point, which is a structure. This is invalid:

{ Location.X = 5,
  Location.Y = 10 } // Invalid.

Instead, I’d need to write:

{ Location = { 5, 10 } } // valid.

But hey, value types should be immutable anyway (Item 7 in Effective C#), and here is yet another example why.

Object Initializers and Collection Initializers do have real uses, beyond mere syntactic sugar. In later entries, you’ll see how they are used with anonymous types to create more dynamic systems.

(For completeness, the Product class definition follows. In production code, I’ve argued against public data members, but this is an instructive sample, not production code.)

public class Product
{

  public int ProductID;

  public string ProductName;

  public string Category;

  public decimal UnitPrice;

  public int UnitsInStock;

}

So, what have we learned here? You saw Object Initializers and Collection Initializers. This new syntax provides a shorthand method of initializing objects and collections. It’s more compact, and retains the same strong typing.

The next entry will discuss Linq samples 3, and 4.



Posted by wwagner | with no comments
Filed under: ,
Our .NET User Group will be building software for regional non-profits

Our user group (www.migang.org) is hosting Andy Wolber from NPower Michigan this month for our tutorial session. He's going to be discussing NPower Michigan, and how we (the user group), can work with them to develop software that helps our regional non-profit organizations achieve their goals.  If you're interesting in how you can use your .NET development skills to aid your community come by.

But wait, there will be some deep technical content following Andy's presentation. Stacy Harris will discuss how you can improve .NET application load times (http://www.migang.org/Default.aspx?tabid=22)

More details on Andy's discussion at the link below.



Press release on Andy's presentation
Background on our user group, Andy, and NPower
Posted by wwagner | with no comments
Filed under:
The one where I explain the syntax in the first query sample

I’ve been spending some time looking at the LINQ samples Microsoft (like many of you). When I do research on new technology, I take lots of notes. (If you have looked at the Microsoft samples, you’ve undoubtedly noticed the lack of comments or other supporting documentation.)

After a couple discussions, I’ve been convinced to post my notes here. So, over the course of the next N entries (for some number N), I’ll post the notes and thoughts I’ve been writing as I go through the LINQ samples. After that’s done, I’ll post some of my thoughts on how one might extend the capabilities of LINQ to other use cases.

These are my notes, not finished articles, so they are rough. But, I hope you get some insight into LINQ, and how I research new topics. You’ll be following along as I unravel the snarl, not picking up a nice straight piece of string.

Starting at the beginning: Sample Queries

The first set of samples runs the 101 LINQ sample queries explorer. The first sample is really quite simple:

[Category("Restriction Operators")]
[Title("Where - Simple 1")]
[Description("This sample uses where to find all elements of an array less than 5.")]
public void Linq1() {
  int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

  var lowNums = // See note 1
    from n in numbers // See note 2
    where n < 5 // see note 3
    select n; // See note 4 

  Console.WriteLine("Numbers < 5:");
  foreach (var x in lowNums) {
    Console.WriteLine(x);
  }
}

The logic here is pretty simple, but the syntax is new and can be unsettling.

Note 1: var syntax. lowNums is strongly typed, not some amorphous thing. A quick examination in the debugger tells you that lowNums is of type “System.Collections.Generic.IEnumerable<int>”. The C# compiler infers the type from the return value of the ‘from’ expression. But wait, it’s not that simple. After you execute that statement, the runtime type of lowNums is actually a System.Query.Sequence.Where<int>. (You can learn more about this class by loading the source. It comes with the LINQ preview, and will be in C:\\Program Files\\LINQ Preview\\Docs\\Sequence.cs.) Sequence is a static class that contains a number of extension methods for many common queries.

For now, understand that any variable declared as ‘var’ is typed to match the compile time type of the expression, not the runtime type. (Here IEnumerable<int> vs. Where<int>).

Note 2: From clause. The from clause, “from n in numbers” declares a variable for a single element in the collection, in this case ‘n’, and the collection being examined, in this case, ‘numbers’. Simple, right?

Note 3: Where clause. The C# compiler translates the ‘where’ clause into a method invocation. In this case, the method is the supplied ‘where’ extension method. One of the where methods (there are a number of overloads) takes a single predicate that returns a bool, and has a single parameter that is the instance of a type. Here’s its implementation from Sequence.cs:

public static IEnumerable<T> Where<T>(
  this IEnumerable<T> source, Func<T, bool> predicate) 
{
  foreach (T element in source)
  {
    if (predicate(element)) yield return element;
  }
}

(Note that this uses the yield statement added in C# 2.0). This code sample introduces another new syntax element for C# 3.0: Notice that the first parameter to Where (source) has the ‘this’ modifier. That denotes an extension method. An extension method is a static method that syntactically servers as an instance method. You could have written the where clause as:

numbers.Where( n => n < 5 );

‘Where’ behaves like it is an instance method to the int[] class (numbers is an instance of that). The parameter to Where is a lambda expression, meaning “n in which n is less than 5”. Simple, right?

The reason for this syntax is so that you (or anyone) can add new methods that work with existing collections.

Note 4: Select clauses.

The final part is this simple method is to return the right fields or properties from the target object. Select determines which properties from the objects in the collection are returned. Here, it trivially returns the iteration variable.

Some notes on the test harness.

If you look back at that sample again, you’ll find three attributes at the top of the method: Category, Title, and Description. These samples use attributes and reflection to build the UI that contains the samples. This technique has been possible since C# 1.0, and I used a version of it in Effective C# (Items 42 and 43)

A few mindless closing remarks

OK, this turned out longer than I thought it would (two pages for 5 lines of code). But, learning something completely new often works that way. As I post notes from other samples, we’ll drill deeper into the concepts you’ve seen here. Hopefully, some of the notes will get shorter, but some will go into more depth.



Posted by wwagner | with no comments
Filed under: ,
Dan Gilmor shows his politics, but not his logic skills

Dan Gilmor wrote this piece touting Wisconsin's law that any software for electronic voting machines must be open-sourced. His claim is that it will lead to fairer election software.

That's completly irrelevant. How does providing source code to a bunch of congress critters (who couldn't write software to save their collective rear ends) going to guarantee that said software works as specified?  

A much stronger, and better plan would be to have a stringent set of tests that any voting machine software must pass before acceptance. Include several test sets, make sure that the order of candidates are reversed, run through the cancel sequences, power interruptions, etc. The open-ness, or close-ness of the source code should not enter into it at all. Right? Does it work, or does it not? That's all I personally care about, and it should be the only thing that matters.

Note: The article referenced has since been updated to point out that the actual requirement is to escrow the software in case of a recount, which makes more sense. That provides the government with a copy of the code (object code and source code) that was installed and running at election time.  It would make it much easier to prove, or disprove, and software bugs or malicious intent on the part of a politically motivated vendor.



Posted by wwagner | with no comments
Filed under:
Reappointed as an RD, and now a C# MVP as well

Just a quick note that I have been reappointed as the Microsoft Regional Director for MI. In that role, I'll continue working to grow the .NET user groups in our area. We have groups in Southfield, Grand Rapids, and Lansing.  I'll try and speak at all of those once this year. We're also in the process of creating a group in Ann Arbor. 

From the technology side, I'll be focusing on C# 2.0 (now that it's released), and C# 3.0 (at least LINQ, which has been announced).  That gets to my second announcement:  I've been awarded C# MVP status, as of Januaray of this year. In that role, I'll be doing much as I have been already:  writing articles and giving presentations about the current and future versions of the C# language, and the .NET Base Class Library (BCL).  The MVP status means I now have more resources at my disposal to better understand and explain all the new features being added to my favorite programming language.



Posted by wwagner | with no comments
Filed under: