0

I'm adding validation attributes to the properties of my class. I have a library, let's just say a third party library, that contains a StringLengthAttribute. We know that there's an attribute with the same name under System.ComponentModel.DataAnnotations.
I'm using both the third party and System.ComponentModel.DataAnnotations in the class that I'm creating. That causes an ambiguity on StringLengthAttribute. The compiler suggested to use @ in the attribute like this [@StringLength()]. That's what I did, but when I tried to F12(Go to definition) it brought me to the third party library.

I would like to understand how the @ sign in the attribute really works and I want to use the System.ComponentModel.DataAnnotation.StringLengthAttribute rather than the third party, how should I do that given that both namespaces of the thirdparty and DataAnnotation are declared on the using part on top of the class.

[@StringLength(10)]
public string Name { get; set; }
Camilo Terevinto
  • 31,141
  • 6
  • 88
  • 120
Lance
  • 2,774
  • 4
  • 37
  • 57
  • It doesn't do what you think it does. It does what @wablab says. You are asking how something works a certain way when it doesn't work that way, so there is no possible answer. The only solution to your problem is to use the fully qualified namespace for the attributes. – Erik Funkenbusch Jun 30 '16 at 17:43

1 Answers1

2

C# offers some syntactic sugar that allows you to omit the word Attribute when adorning a member with an attribute. For example, if you have an attribute named MyCustomAttribute, you can use this shorthand when applying it to a method:

[MyCustom]
public void MyMethod()
{
  ...
}

This is great, until you also declare a class named "MyCustom" that also derives from Attribute. In such a case, the C# compiler wouldn't know whether [MyCustom] was meant to refer to your MyCustom class or to your MyCustomAttribute class. By prefixing your attribute usage with @, you're telling the compiler that you mean to use the class with exactly the name that follows the @ (i.e. the compiler should not append "Attribute"). So [@MyCustom] refers to the MyCustom class, whereas [@MyCustomAttribute] would refer to the MyCustomAttribute class.

In your example usage of [@StringLength(10)], the compiler will resolve that attribute to the class named StringLength, not the class named StringLengthAttribute.

Here's an example from the C# language spec that probably explains this better than I did:

[AttributeUsage(AttributeTargets.All)]
public class X : Attribute
{}

[AttributeUsage(AttributeTargets.All)]
public class XAttribute : Attribute
{}

[X]                  // Error: ambiguity
class Class1 {}

[XAttribute]         // Refers to XAttribute
class Class2 {}

[@X]                  // Refers to X
class Class3 {}

[@XAttribute]         // Refers to XAttribute
class Class4 {}
wablab
  • 1,703
  • 13
  • 15
  • In my case, the attribute both have the same names which is StringLengthAttribute. How did it know that I'm referring to the third party and not the one in DataAnnotation? By the way, I can always put the fully qualified name to clearly state which attribute I want to use. I just want to understand this syntactic sugar. – Lance Jun 30 '16 at 17:38
  • If the file where you've applied the `StringLengthAttribute` only has a `using` statement for the namespace that contains the third-party class and not a `using System.ComponentModel.DataAnnotations;` then that would explain how the compiler was able to choose. If `using` statements are present for both classes, then perhaps the third-party version is the only one with a constructor that accepts an `int` as a lone parameter (although I would've expected that to result in a compile error). If both classes have a constructor with this type of overload, then I don't know how it's working. – wablab Jun 30 '16 at 17:43