# Monday, November 21, 2005
« Going to VS Launch in Vancouver and Calg... | Main | The Count of Monte Bristowe, St. Jerome ... »

We’re now at least half way into this set of posts on factoring features in Visual Studio 2005. The more I’ve thought about getting this set of posts fully written up, the more I’ve found these features interesting. My team produced them, so that helps, but I believe that a lot of developers will end up needing these features as a part of their versioning plan.

 

AKA InternalsVisibleTo

Friend assemblies are a nickname for the InternalsVisibleTo attribute in the System.Runtime.CompilerServices namespace. Not much of a stretch from the name, the use of the attribute allows you to specify which assemblies (your friends) should have access to your internal types and members. Just to remind you, “internal” != “private” – “internal” == “internal”.

 

As you might guess, this attribute must be set at the assembly-level. You might hope, however, that you could set this attribute at a more fine-grained level. I can explain that more later.

 

Syntax

The attribute is set in the following way:

 

[assembly:InternalsVisibleTo(“MyOtherAssembly, PublicKey=4asdsadasdsd”)

 

Couple things … The constructor of the attribute -- remember attributes are just types -- takes a textual assembly identity. Next, you must specify at least an assembly name and optionally a public key token. You can specify a culture as long as it is neutral. You cannot specify a version. Some of this may be a surprise to you. I’ll explain that below.

 

Design Decision Points

In retrospect, I’m not sure that making the public key token optional was the absolute best idea, but it was probably was necessary for a lot of interesting scenarios. First, friend assemblies is not a security feature, in the sense that visibility is not a security feature. Friend assemblies is just about changing the usual bounds of visibility to something that is more convenient for developers in a lot of cases.

 

That all being said, friend assemblies are really best kept to strong-named assemblies. Weak- or simple-named are very easily spoof-able (by definition). As a result, someone can simply use a particular name for their assembly and then get access to the internal fields in a simply-named assembly from which you’ve granted friendship. Even if you only ship your code internally within your business, this still isn’t a great plan. Think about it for a while and you’ll probably begin to better understand why.

 

It probably mostly goes without saying, but strong-named assemblies can only have strong-named friends. Strong-named assemblies can only depend on strong-named assemblies, so this point is moot anyway.

 

I do feel strongly that disallowing the version number was the right thing to do. The reason for that is that CLR binding doesn’t always produce the version of an assembly that you expect. There are a lot of mechanisms that can be at play, such as publisher policy, binding-redirects and other binding/versioning changes that we have planned for the CLR v3. As a result, you cannot assume that an assembly that depends on you is always going to be the same. Remember, with friends, it isn’t that you are assuming that a dependency of yours is going to be a particular version, but an assembly that is dependent on you. We would have potentially made a different decision if friends was the opposite way around, being a statement about your dependencies, but it isn’t.

 

The ability to specify culture provided that it is neutral is mostly a red-herring. There is no harm to specifying it, which is why we allowed it, but it is best to think in general that culture isn’t allowed. The main reason here is that you should not have code in culture-specific assemblies.