Today I decided to take a look at Windows Phone 7 development. The first thing I did was download the Windows Phone Developer Tools, you can download it here: http://www.microsoft.com/express/phone/ Windows Phone Developer Tools includes: Visual Studio 2010 Express for Windows Phone Windows Phone Emulator Silverlight for Windows Phone XNA Game Studio 4.0 CTP The download was 228 MB for me, I already had Visual Studio 2008 and Visual Studio 2010 RC on my machine, if you don’t have those, the download might be bigger.
This is an archive of the posts published to LessThanDot from 2008 to 2018, over a decade of useful content. While we're no longer adding new content, we still receive a lot of visitors and wanted to make sure the content didn't disappear forever.
Introduction Every week in my shop we do cross training. Someone brings in something they are working on, some system that people are unfamiliar with, some new technology, basically anything related to any of our jobs as developers and maintainers of applications. Often enough I do presentations on Silverlight and Blend, introducing my coworkers to different tools and options that we have available to us. This blog is a write up of one such training presentation. I give you, the Silverlight Spinner.
In an IT department there is a tendency to classify operations as being reactive or proactive and, often, pressure to have more of the latter and less of the former. Pressure, that is, until a PC breaks down, a network connection drops, a data record goes missing, or any of a dozen other issues which will ultimately receive more attention than disaster recovery, employee development, business analysis, strategic planning and the rest of a long list of proactive tasks. Immediate, defined problems are far easier to focus on than tenuous concepts of proactive prevention.
I don’t know how many times I’ve put together the same slow regexp to check if the user input is a valid phone number. I decided that this cannot go on and developed a simple phone number primitive. Now our main concern here is the performance of TryParse since it will be used the most. After running some performance tests the median timing was 400ns on a 3Ghz machine. [Serializable] public struct PhoneNumber : IEquatable<PhoneNumber> { private const int AreaCodeShift = 54; private const int CentralOfficeCodeShift = 44; private const int SubscriberNumberShift = 30; private const int CentralOfficeCodeMask = 0x000003FF; private const int SubscriberNumberMask = 0x00003FFF; private const int ExtensionMask = 0x3FFFFFFF; private readonly ulong value; public int AreaCode { get { return UnmaskAreaCode(value); } } public int CentralOfficeCode { get { return UnmaskCentralOfficeCode(value); } } public int SubscriberNumber { get { return UnmaskSubscriberNumber(value); } } public int Extension { get { return UnmaskExtension(value); } } public PhoneNumber(ulong value) : this(UnmaskAreaCode(value), UnmaskCentralOfficeCode(value), UnmaskSubscriberNumber(value), UnmaskExtension(value), true) { } public PhoneNumber(int areaCode, int centralOfficeCode, int subscriberNumber) : this(areaCode, centralOfficeCode, subscriberNumber, 0, true) { } public PhoneNumber(int areaCode, int centralOfficeCode, int subscriberNumber, int extension) : this(areaCode, centralOfficeCode, subscriberNumber, extension, true) { } private PhoneNumber(int areaCode, int centralOfficeCode, int subscriberNumber, int extension, bool throwException) { value = 0; if (areaCode < 200 || areaCode > 989) { if (!throwException) return; throw new ArgumentOutOfRangeException("areaCode", areaCode, @"The area code portion must fall between 200 and 989."); } else if (centralOfficeCode < 200 || centralOfficeCode > 999) { if (!throwException) return; throw new ArgumentOutOfRangeException("centralOfficeCode", centralOfficeCode, @"The central office code portion must fall between 200 and 999."); } else if (subscriberNumber < 0 || subscriberNumber > 9999) { if (!throwException) return; throw new ArgumentOutOfRangeException("subscriberNumber", subscriberNumber, @"The subscriber number portion must fall between 0 and 9999."); } else if (extension < 0 || extension > 1073741824) { if (!throwException) return; throw new ArgumentOutOfRangeException("extension", extension, @"The extension portion must fall between 0 and 1073741824."); } else if (areaCode.ToString()[1] - 48 > 8) { if (!throwException) return; throw new ArgumentOutOfRangeException("areaCode", areaCode, @"The second digit of the area code cannot be greater than 8."); } else { value |= ((ulong)(uint)areaCode << AreaCodeShift); value |= ((ulong)(uint)centralOfficeCode << CentralOfficeCodeShift); value |= ((ulong)(uint)subscriberNumber << SubscriberNumberShift); value |= ((ulong)(uint)extension); } } public override bool Equals(object obj) { return obj != null && obj.GetType() == typeof(PhoneNumber) && Equals((PhoneNumber)obj); } public bool Equals(PhoneNumber other) { return this.value == other.value; } public override int GetHashCode() { return value.GetHashCode(); } public override string ToString() { return ToString(PhoneNumberFormat.Separated); } public string ToString(PhoneNumberFormat format) { switch (format) { case PhoneNumberFormat.Plain: return string.Format(@"{0:D3}{1:D3}{2:D4} {3:#}", AreaCode, CentralOfficeCode, SubscriberNumber, Extension).Trim(); case PhoneNumberFormat.Separated: return string.Format(@"{0:D3}-{1:D3}-{2:D4} {3:#}", AreaCode, CentralOfficeCode, SubscriberNumber, Extension).Trim(); default: throw new ArgumentOutOfRangeException("format"); } } public ulong ToUInt64() { return value; } public static PhoneNumber Parse(string value) { var result = default(PhoneNumber); if (!TryParse(value, out result)) { throw new FormatException(string.Format(@"The string ""{0}"" could not be parsed as a phone number.", value)); } return result; } public static bool TryParse(string value, out PhoneNumber result) { result = default(PhoneNumber); if (string.IsNullOrEmpty(value)) { return false; } var index = 0; var numericPieces = new char[value.Length]; foreach (var c in value) { if (char.IsNumber(c)) { numericPieces[index++] = c; } } if (index < 9) { return false; } var numericString = new string(numericPieces); var areaCode = int.Parse(numericString.Substring(0, 3)); var centralOfficeCode = int.Parse(numericString.Substring(3, 3)); var subscriberNumber = int.Parse(numericString.Substring(6, 4)); var extension = 0; if (numericString.Length > 10) { extension = int.Parse(numericString.Substring(10)); } result = new PhoneNumber( areaCode, centralOfficeCode, subscriberNumber, extension, false ); return result.value != 0; } public static bool operator ==(PhoneNumber left, PhoneNumber right) { return left.Equals(right); } public static bool operator !=(PhoneNumber left, PhoneNumber right) { return !left.Equals(right); } private static int UnmaskAreaCode(ulong value) { return (int)(value >> AreaCodeShift); } private static int UnmaskCentralOfficeCode(ulong value) { return (int)((value >> CentralOfficeCodeShift) & CentralOfficeCodeMask); } private static int UnmaskSubscriberNumber(ulong value) { return (int)((value >> SubscriberNumberShift) & SubscriberNumberMask); } private static int UnmaskExtension(ulong value) { return (int)(value & ExtensionMask); } } public enum PhoneNumberFormat { Plain, Separated }
Internet Explorer 9 is available for a test drive Microsoft detailed its support for a number of HTML5 specifications, including CSS3, Scalable Vector Graphics (SVG), XHTML parsing, and the video and audio tags using industry-standard (H.264/MPEG4 and MP3/AAC) codecs, among others. In addition, Microsoft demonstrated a new JavaScript engine that uses the multiple cores of today’s modern chips to effectively manage computing resources and improve Web performance. By combining increased interoperability with a new JavaScript engine and Direct 2D technology, Internet Explorer 9 enables Web developers to provide users with richer experiences that render more quickly and consistently.
Yesterday I made a post about using a queue instead of a list because the code was so much cleaner. I think it is very important that code is clean and easier to read. But then Denis asked about the performance differences between the 2 methods. I hadn’t worried about the performance, because in my case the performance was good in both cases. But I aim to please my fellow LTDers, so I did a little performance test. And let me remind you that like most performance tests, this one is flawed as well.
I was doing this in my code. Private _Lines As New Collections.Specialized.StringCollection Private Const _MaxLines As Int16 = 30 Private Sub SetMessages(ByVal message As String) If _Lines.Count > _MaxLines Then _Lines.RemoveAt(_MaxLines - 1) End If _Lines.Add(DateTime.Now.ToString("HH:mm:ss") & " - " & message & Environment.NewLine) Dim text As New System.Text.StringBuilder For _temp As Integer = _Lines.Count - 1 To 0 Step -1 text.Append(_Lines(_temp)) Next Me.txtMessages.Text = text.ToString End Sub``` Look Mama, I made a queue. <div class="image_block"> <img src="https://lessthandot.z19.web.core.windows.net/wp-content/uploads/blogs/DesktopDev/queue/queue.gif" alt="" title="" width="295" height="277" /> </div> Oh wait, there is a queue object that I should have used. ```vbnet Private _Lines As New Queue(Of String)(30) Private Const _MaxLines As Int16 = 30 Private Sub SetMessages(ByVal message As String) _Lines.Enqueue(DateTime.Now.ToString("HH:mm:ss") & " - " & message & Environment.NewLine) If _lines.Count > _maxlines Then _lines.Dequeue() Me.txtMessages.Text = "" For Each line As String In _lines.Reverse Me.txtMessages.AppendText(line & Environment.NewLine) Next End Sub``` That is much shorter. Sometimes I amaze myself ;-). Of course, it would be even shorter if I had used a ListBox. ```vbnet Private _Lines As New Queue(Of String)(30) Private Const _MaxLines As Int16 = 30 Private Sub SetMessages(ByVal message As String) _Lines.Enqueue(DateTime.Now.ToString("HH:mm:ss") & " - " & message & Environment.NewLine) If _lines.Count > _maxlines Then _lines.Dequeue() Me.ListBox1.DataSource = _lines.Reverse.ToList() End Sub``` So use the power of [Q][1]. Just for Denis I did a [followup on this post][2]. [1]: http://en.wikipedia.org/wiki/File:Q_%28Star_Trek%29.jpg [2]: /index.php/DesktopDev/MSTech/use-the-right-collection-part-2
Visual Studio 2010 and .NET 4.0 are almost released, one of the new things that ship with this release is Parallel Programming. Since you can’t buy a machine anymore with just one core it is time that we developers get intimate with concurrent programming. I decided to play around with this a little today, this is not a real technical post, I mostly show you how you can get started and what new tools are available.
Are you waiting for .NET 4.0 to take advantage of lazy initialization? Now you don’t have to. The question you need to ask yourself is why haven’t I already made this myself? Aren’t we all a little lazy? /// <summary> /// Provides support for lazy initialization. /// </summary> /// <typeparam name="T">Specifies the type of object that is being lazily initialized.</typeparam> public sealed class Lazy<T> { private readonly Func<T> createValue; private volatile bool isValueCreated; private T value; /// <summary> /// Gets the lazily initialized value of the current Lazy{T} instance. /// </summary> public T Value { get { if (!isValueCreated) { lock (this) { if (!isValueCreated) { value = createValue(); isValueCreated = true; } } } return value; } } /// <summary> /// Gets a value that indicates whether a value has been created for this Lazy{T} instance. /// </summary> public bool IsValueCreated { get { lock (this) { return isValueCreated; } } } /// <summary> /// Initializes a new instance of the Lazy{T} class. /// </summary> /// <param name="createValue">The delegate that produces the value when it is needed.</param> public Lazy(Func<T> createValue) { if (createValue == null) throw new ArgumentNullException("createValue"); this.createValue = createValue; } /// <summary> /// Creates and returns a string representation of the Lazy{T}.Value. /// </summary> /// <returns>The string representation of the Lazy{T}.Value property.</returns> public override string ToString() { return Value.ToString(); } } Example Usage
Microsoft has released ASP.NET MVC 2 RTM for Visual Studio 2008 SP1. Note Because Visual Studio 2008 and Visual Studio 2010 RC share a component of ASP.NET MVC 2, installing the ASP.NET MVC 2 RTM release on a computer where Visual Studio 2010 RC is also installed is not supported. New Features in ASP.NET MVC 2 RTM The following features are new since the RC release of ASP.NET MVC 2.