Pages

Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Thursday, February 6, 2014

Create implicit and explicit user-defined type converions in C#

I bet you had to write tons of static methods to convert between a user-defined type to another type, and that it always made your code very ugly and verbose, also creating lots of "helpers".

Well, C# has a nifty way to facilitate that for us.

Apart from using the keyword operator to overload default arithmetic operations, we can use it in conjunction with the implicit and explicit keywords to create new user-defined type conversions. One should already know the difference between explicit and implicit conversions.


Implying it


By defining a new operator using the implicit keyword, you can easily hide all of those static method calls, and write simple code, such as this:

var foo = new Foo
{
    Size = 10,
    Name = "Foo"
};

Bar bar = foo;

// Notice that we're not talking about polymorphism, 
// as there's no inheritance between the classes:
class Bar
{
    public string BarInfo { get; set; }
}

class Foo
{
    public int Size { get; set; }
    public string Name { get; set; }       
}

To do that, we simply defined a new implicit operator between the two types, such as:

public static implicit operator Bar(Foo foo)
{
    var bar = new Bar { BarInfo = string.Concat(foo.Size, " - ", foo.Name) };

    return bar;
}

The above code simply concatenates both properties of our Foo object and sets Bar's BarInfo property with the result.

MSDN says that the operator should be defined on the source type, although it works well if you define it on the target type. Also, it states that you should only use implicit conversions for user-defined types like this if you're absolutely sure that no exceptions may be thrown. If there's too much data transformation, and you may eventually get an exception, then it advises you to use explicit conversions instead.


Expliciting it

Let's say we have a Foo type, which already has an implicit conversion to a Bar type. But now there's this new BigFoo type for which we want to convert our Foo. A Foo needs to have a size of at least 10 to be considered a BigFoo. So what we want to do is:

var foo = new Foo
{
    Size = 10,
    Name = "Foo"
};

BigFoo bigFoo = (BigFoo)foo;

And to enable such code, we define an explicit operator between the two types on the Foo class:

class Foo
{
    public int Size { get; set; }
    public string Name { get; set; }       
        
    public static explicit operator BigFoo(Foo foo)
    {
        if (foo.Size < 10)
        {
            throw new InvalidCastException("Foo is not big enough to be a BigFoo!");
        }

        var bigFoo = new BigFoo { Name = foo.Name };

        return bigFoo;
    }
}
I'd rather read the above conversion code examples as they are then reading code that looks like this:
var foo = new Foo
{
    Size = 10,
    Name = "Foo"
};

var bigFoo = Foo.TryConvertToBigFoo(foo);
var bar = Foo.ConvertToBar(bar);

Wednesday, July 31, 2013

Boolean parameter VS exposing semantics

This can be a subject of quite long discussions with team mates during coffee hours.
Some team mates might think that simply putting a boolean parameter that slightly changes the behavior of a method is not a big deal. They may even make the parameter optional.

But when is that a good thing? When is it good to "just add a boolean parameter and make it optional"? Well, if it changes the method behavior in the smallest way possible, but even then it matters, then I'd say it's never good.

To prove it, consider the following two calls:

object.DoSomeLengthyWork();
object.DoSomeLengthyWork(true);

I don't know about you, but if I'm the one maintaining this code the first thing that would pop into my head when reading the second line would be "What the hell should be true?". The second thing I'd have to do would be lookup the method definition (or read its summary, if the developer who wrote the method cared enough to even create one), which is pretty easy, just position the cursor over it and press F12 right? Right! But what if that method is defined in another project / solution / dll that you do not have opened in your environment, or you don't even have access to?

And that, my friend, is why I strongly advise you to always go for the better semantics! Specially if you're writing public methods.

What I'm saying here doesn't make much sense if you work in a small company with a small codebase and maybe a team of 2 to 3 developers. But imagine working in a team of 20, 30 or 50 developers. Or even with a small codebase, imagine maintaining code that has been in production for 5 years or more, with no documentation whatsoever. Code whose owner or writer is not even working for the company anymore. I'm sure you'd have a blast trying to find out "what the hell should be true" in the example above.

Wouldn't it be easier if you could just have those two example lines written like this instead?

object.DoSomeSynchronousLengthyWork();
object.DoSomeAsynchronousLengthyWork();

"Ooooh, so that's what that true meant!"

And I won't even mention named arguments for cases like this, because they're pretty evil for distributed solutions. Jon Skeet has an awesome way of stating it, which can be found here and of course, in his book C# in Depth, that I quote:


The silent horror of changing names

In the past, parameter names haven’t mattered much if you’ve only been using C#. Other languages may have cared, but in C# the only times that parameter names were important were when you were looking at IntelliSense and when you were looking at the method code itself. Now, the parameter names of a method are effectively part of the API even if you’re only using C#. If you change them at a later date, code can break—anything that was using a named argument to refer to one of your parameters will fail to compile if you decide to change it. This may not be much of an issue if your code is only consumed by itself anyway, but if you’re writing a public API, be aware that changing a parameter name is a big deal. It always has been really, but if everything calling the code was written in C#, we’ve been able to ignore that until now.

Renaming parameters is bad; switching the names around is worse. That way the calling code may still compile, but with a different meaning. A particularly evil form of this is to override a method and switch the parameter names in the overridden version. The compiler will always look at the deepest override it knows about, based on the static type of the expression used as the target of the method call. You don’t want to get into a situation where calling the same method implementation with the same argument list results in different behavior based on the static type of a variable.


And that my friends, is why when it comes to boolean parameters VS method overloading, I always side with method overloading, that is, when the boolean parameter changes the method's behavior in a way that matters.

PS: C# in Depth is a great read, you should definitely read it.

Wednesday, August 1, 2012

Using FileSystemWatcher

Undoubtedly one of the most interesting components in the .NET framework, and it's so useful that I was surprised to find out that it exists since the first version of the framework. I’m going to show simple and easy it is to work with.

I’ll adopt the description method first used by Felipe in here:

In my words:

FileSystemWatcher lets you monitor a given directory reporting every detected change, such as files and folders creations, renamings, exclusions, and changes. The most obvious use for it and probably what it’s more used for is automated file processing, for its reliability and speed.

In MSDN’s words:

Listens to the file system change notifications and raises events when a directory, or file in a directory, changes. Use FileSystemWatcher to watch for changes in a specified directory. You can watch for changes in files and subdirectories of the specified directory. You can create a component to watch files on a local computer, a network drive, or a remote computer.

A better look

It’s really a simple component, with few properties and events:

There are only two properties that would need some details:

Filter: A filter for files names and extensions. If you change it to *.txt, only changes made in .txt files will raise events.

NotifyFilter: Which kinds of changes will be used to determine a change. The default ones are enough for regular uses.

Its events are so simple that no further explanation is needed.

Demonstration

By now you should know what it does, and what it could be used for. I’m going to do a little demonstration on how to use it:

We’re going to use a simple form with a FileSystemWatcher, a TextBox, where we’re going to get the path to be watched from the user, and a button, to start monitoring.

To avoid having three methods that do the same thing, we’re going to use the same one to handle three of the events, Changed, Created and Deleted, since the three of them use the same signature. And an additional method for the Renamed event, as one of its arguments is not the same (to carry along the old name of the renamed file).

private void frmMain_Load(object sender, EventArgs e)
{
Watcher.Renamed += new RenamedEventHandler(Renamed);
Watcher.Deleted += new FileSystemEventHandler(Changed);
Watcher.Changed += new FileSystemEventHandler(Changed);
Watcher.Created += new FileSystemEventHandler(Changed);
}


Then we can set our two methods to handle these events, Renamed and Changed:

void Changed(object source, FileSystemEventArgs e)
{
string item = e.ChangeType + ": "+ e.Name;

lstChanges.Items.Add(item);
}

void Renamed(object sender, RenamedEventArgs e)
{
string item = "Renamed from: " + e.OldName + " to: " + e.Name;

lstChanges.Items.Add(item);
}

Now all we’ve got to do is to define what the Button is going to do:

private void btnStart_Click(object sender, EventArgs e)
{
try
{
Watcher.Path = txtPath.Text;
Watcher.EnableRaisingEvents = true;
}
catch (ArgumentException ex)
{
MessageBox.Show("This path does not exist: " + ex.Message);
}
}

Note: I don’t handle exceptions in any of these example codes to make it cleaner, but in this code above it’s really important, since it’s going to use the user input.

In case you’ve created the FileSystemWatcher programmatically, not by clicking the component on the Toolbox, then you have to take care of one more thing: a property of the watcher, SynchronizingObject. This is automatically taken care of by Visual Studio when you use it directly from the Toolbox, which is this demonstration’s case, but if you don’t, you just have to assign the form where you’re using to display the changes to the SynchronizingObject property like this:

Watcher.SynchronizingObject = this;

This code should be in the form, preferably right after the creation of the FileSystemWatcher instance.

Now we’re all set! Check below how this demonstration performed in a simple test:

Project

Felipe and I have been recently working on our first project in conjunction, and it’s entirely based on this component. I have to say that it’s getting really good, and we’re going to make the source code available, and then I’ll make a post about it in here.