I wanted to call out a fairly simple pattern that shows up in our libraries 
that folks largely haven't caught onto in the patches that they've been 
submitting:

Wayne recently submitted a patch for exist? and exists? which fixes bug #19626:

[RubyMethod("exist?", RubyMethodAttributes.PublicSingleton)]
[RubyMethod("exists?", RubyMethodAttributes.PublicSingleton)]
public static bool Exists(object self/*!*/, MutableString/*!*/ path) {
    return File.Exists(path.ToString()) || Directory.Exists(path.ToString());
}

While this works fine, if you pass it legal arguments, it blows up when the 
invariants are broken (eg path == null). You can see it blow up when you run 
the specs for this method from the command line via:

rake spec file exist dox

To make this patch complete, you'll need to add an overload that accepts a 
nullable object parameter, and add a [NotNull] attribute to the previous 
overload:

[RubyMethod("exist?", RubyMethodAttributes.PublicSingleton)]
[RubyMethod("exists?", RubyMethodAttributes.PublicSingleton)]
public static bool Exists(object self/*!*/, [NotNull]MutableString/*!*/ path) {
    return File.Exists(path.ToString()) || Directory.Exists(path.ToString());
}

[RubyMethod("exist?", RubyMethodAttributes.PublicSingleton)]
[RubyMethod("exists?", RubyMethodAttributes.PublicSingleton)]
public static bool Exists(CodeContext/*!*/ context, object self/*!*/, object 
path) {
    return Exists(self, Protocols.CastToString(context, path));
}

Notice how the null case is taken care of by Protocols.CastToString(). It also 
will handle the case where the user passes a string that can 'act like' a 
string by implementing to_str. This is an *extremely* common case in the Ruby 
libraries.

The [NotNull] attribute is used by the binder to ensure that a null is never 
passed as a parameter to the first overload, but instead directs the caller to 
the second overload. This is the case which correctly handles null (and is also 
reflected by the fact that we are declaring via comments that path is 
*nullable* eg missing the spec# bang).

Let me know if this isn't clear or needs some further clarification.

Thanks!
-John

_______________________________________________
Ironruby-core mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/ironruby-core

Reply via email to