Google Mail Ads
Just a fun thing that happened today: I was sending a mail in GMail, and noticed that the customized ads displayed something that could be considered “offensive” to me, in a fun way:
Mr. Google is lying. C# rocks!
Comparing a Value Type with null does not box
Recently, I discovered something like this my current codebase:
var g = Guid.NewGuid(); if (g == null) throw new Exception("Exception");
Of course, there are other statements in between, this is just an over simplifications. The idea, however, is to compare a value type with null, which makes no sense if you know .NET a bit, but can be found all over the world I am sure.
Without checking, I was sure that this would result in boxing the value type, followed by a comparison of the reference of the box with null, which will always return false.
Well, it turns out that I was wrong. The compiler is smart enough and ignores the statement in this case, as it is useless.
Now, what if there is an else statement in there?
if (g == null) throw new Exception("Exception"); else Console.WriteLine("boxed?");
In this case, the compiler only emits that is in the else statement. It is once more smart enough.
Let’s push it a little bit. What happens if we do this:
var b = (g == null); if (b) Console.WriteLine("boxed?");
In this case, the compiler will emit all the instructions, although it’s obvious that Console.WriteLine will never be executed. But still, no boxing.
Once more, C#’s compiler is very smart about all this. There is no boxing happening in the three cases.
Copy a Field’s Value to another Field in SharePoint
If one of your field data type needs to be changed, you will run into issues when deploying the new version of your application, as SharePoint can’t translate from one data type to another. For example, if you change a field type from “Single Line of Text” to “Notes” in Fields.xml, everything will go wrong.
The clean way to do this is to create a new field, the one that will be used from now on, and copy the value of the old field to the new field, while applying a transformation if necessary.
For this, we wrote a generic method that will go trough the entire site and perform the changes on the specified fields.
public static void CopyFieldValues(SPSite site, String copyFromFieldInternalName, String copyToFieldInternalName, Func<Object, Object> transformation) { foreach (SPWeb web in site.AllWebs) { //Get all the ListItems in every list of the web that has the 2 fields var items = (from l in web.Lists.Cast<SPList>() where l.Fields.ContainsField(copyFromFieldInternalName) && l.Fields.ContainsField(copyToFieldInternalName) from i in l.Items.Cast<SPListItem>() select i).ToList(); //For each listitem in this web, migrate the content of the old one to the new one //To do this, we use the tranformation Func that was given as a parameter foreach (SPListItem item in items) { item[copyToFieldInternalName] = transformation(item[copyFromFieldInternalName]); //Do system update to avoid modifying the item's version item.SystemUpdate(false); } } }
So, now that we have a generic method to copy the content of a field into another, we can “specialize” it for various uses.
One example is migrating a Single Line of Text type field to a Note type field. It is very easy because there is no transformation needed:
public static void CopyFieldValuesFromSingleLineOfTextToNote(SPSite site, String copyFromFieldInternalName, String copyToFieldInternalName) { //No need to transform the data in this case SharePointFieldsHelper.CopyFieldValues(site, copyFromFieldInternalName, copyToFieldInternalName, oldFieldValue => oldFieldValue); }
More on IsSPBuiltInField…
Some follow up on my previous post…
I had to work with this a bit more today, so I wrapped it up a bit to make it more convenient to work with:
public static class SPFieldExtension { static IDictionary<Guid, bool> PublishingBuildInFields { get; set; } static SPFieldExtension() { Type type = typeof(FieldId); var propInfoArray = type.GetProperties(BindingFlags.Static | BindingFlags.Public); SPFieldExtension.PublishingBuildInFields = propInfoArray .Select(prop => (Guid) prop.GetValue(null, null)) .ToDictionary(g => g, g => true); } /// <summary> /// Check if the given field is a build in field of SharePoint (WSS and MOSS) /// </summary> /// <param name="guid"></param> public static bool IsSPBuiltInField(Guid guid) { return SPBuiltInFieldId.Contains(guid) || SPFieldExtension.PublishingBuildInFields.ContainsKey(guid); } /// <summary> /// Check if the given field is a build in field of SharePoint (WSS and MOSS) /// </summary> /// <param name="field"></param> public static bool IsSPBuiltInField(this SPField field) { return SPFieldExtension.IsSPBuiltInField(field.Id); } }
So, I created a static class to hold my two methods. One is the same a the one in the previous post, taking a Guid and returning a Boolean. The second one is an extension method for SPField that simply call the first method. It’s more continent to use it this way.
Is a given Field one of SharePoint’s Built-In Field?
We struggle with this issue on my current project. The issue itself is rather trivial: we have a field (actually, the Guid of a field) and we want to know if it is one of SharePoint’s built-in field or if it is a custom field from our application.
Now, as our application runs on MOSS 2007, there are two kind of built-in fields: those of WSS 3.0 and those of MOSS 2007. For WSS 3.0 fields, there is a class named SPBuiltInFieldId that has all the built-in fields’ guids as public fields and the class even has a static method Contains that allows to quickly find out if the field is built-in from WSS 3.0 or not.
For MOSS 2007 fields, there is the Microsoft.SharePoint.Publishing.FieldId class that has all the built-in fields’ Guids as public properties, but unfortunately does not have a “Contains” method.
So how are we going to find out? Obviously, we are not going to compare against all the properties of the FieldId class… No, let’s do this the clean way: make use reflection to build up a Dictionnary with all the Guids then we’ll use that table to check if our field is in it or not!
static IDictionary<Guid, bool> PublishingBuildInFields { get; set; } static Program() { Type type = typeof(Microsoft.SharePoint.Publishing.FieldId); var propsInfoArray = type.GetProperties(BindingFlags.Static | BindingFlags.Public); PublishingBuildInFields = propsInfoArray .Select(prop => (Guid)prop.GetValue(null, null)) .ToDictionary(g => g, g => true); } bool IsSPBuiltInField(SPField field) { return SPBuiltInFieldId.Contains(field.Id) || PublishingBuildInFields.ContainsKey(field.Id); }
Now, one interesting detail is that ToDictionary uses immediate execution, so we are sure to execute reflection calls only once, during the static constructor’s execution. This is important, because if we just built a sequence with Select, every time we could access that sequence the reflection code would execute, which is not a good idea in most cases.
Update: follow up here.
