Why static import is bad…

John Rusk asked me to elaborate on why I think static import is bad.

It's all about readability. Most people agree that the average line of source code is read far more times than it is written, which means that being able to understand the line is more important than being able to write it quickly.

Static import is bad because it adds an exception to the rules that everybody has to know and remember. If you see

int x = Process(s);

it's a line of code that's easy to understand, because you know what Process is, and more importantly, you know where to go look for it.

But if you add the capability of doing static imports, Process() can now come from other places, so you have to keep that in the back of your mind, and may have to traipse back to find the import statement. A good IDE could help out at this, but I don't think that should be a language design point.

One can argue that for its intended use - things like Math.Sin(), it will make things clearer, which I agree with. The problem is that I can see this feature being used by people who are familiar with their code to save time, and for them it's obvious that they've done that, but that's not true for the poor guy who inherits the code.

Any feature that comes with the kinds of warnings that were given at the introductions yesterday is questionable in my book, and I don't like adding something that has a good potential to be abused to address a case where people are doing the wrong thing already.

Of course, you can argue that C# has lots of areas of potential abuse, and I'd have to agree with you there, though I think the utility of those features is higher than merely saving a few keystrokes.

Comments (22)

  1. Juan Felipe Machado says:

    I agree 100% with you, PLEASE DON’T add static import support to C#, I always hate those languages where you can do that, they’re SO HARD to read!!!

  2. I’m so happy to read this! Static imports is easily the worst Java language feature *ever*.

  3. Jonathan says:

    I tend to agree.

    I think the issue is more 90% runtime and 10% compiler.(if that).

    As I said in your initial post (http://blogs.msdn.com/ericgu/archive/2004/06/29/169394.aspx?Pending=true)

    ,I think its about intervention, not code weaving.

    I think that many (I am not referring to you or readers) confuse the benefit of hooking in, with what AOP really is all about.

    AOP causes chaos in terms of readability and the changed quantities. But instilling an "intervention philosophy" is *no more * complicated than understanding threads /polymorphism / observer and factory patterns.

  4. Justin Rudd says:

    How about a with statement like in VB? I build a lot of datasets by hand and I’m tired of writing…


    I would love to be able to do like in VB.NET

    With ds.Tables


    End With

    Considering it is a block of code, I don’t feel that readability is lost.

  5. Carlos says:

    Nested "with" blocks can be very obscure. If you have a couple of complicated objects and a complicated expression involving several properties from both it is very hard to see what’s going on.

    To avoid this, members should be resolved against the innermost "with" block only.

  6. Lee says:

    Maybe I’m ignorant, but can you explain to me why static import in Java is bad, but the using statement in C# is ok?

    C# allows you to do things that turn this:


    into this:

    using Math;








    While it is easy to see in the VS IDE where Sin comes from by mousing over it, isn’t that the same principle as static imports?

  7. Eric says:


    It’s not possible to do what you say in C#. I think, but am not sure, that you can do it in VB

  8. John Rusk says:

    >One can argue that for its intended use – things like Math.Sin(), it will make things clearer, which I agree with. The problem is that I can see this feature being used by people who are familiar with their code to save time, and for them it’s obvious that they’ve done that, but that’s not true for the poor guy who inherits the code.

    I’ve wished we had it for the likes of Math.Sin(). But, I must admit that your reasoning makes sense. Thanks for sharing it with us.


  9. Darren Oakey says:

    No, no, no

    Let’s start with two assertions:

    a) when coding, nothing is more important than simplicity and readability

    b) my test of readability =

    "how long would it take someone who spoke english, but has never seen a computer in their life, to understand the code"

    I DO NOT accept that code should be optimized for understanding by an expert in C#. I have programmed in too many languages in my life to believe with confidence that I won’t have to be coding in a different one in two years. I code in patterns and in english… the syntax of the language is an afterthought!

    If you don’t at least tolerate those assertions, don’t bother reading the rest of the post..

    Now, onto static imports…

    == usage ==

    first, let me say, in 98% of the code I wouldn’t use it… For most objects you want to see what object the operation is on, and anyway, for most objects you don’t have static operations except for factories, and in the "Employee.Create" – you very much want to see the "Employee" bit!!

    However, on the flip site, the 2% of code you would want to directly use appears in 90% of the rest of your code… it’s all your common libraries – core system code, and when it comes down to it, stuff that you feel was "left out" of the standard libraries. This code is common across the board, and it’s truly disadvantageous to have it in a class. We all know the maths examples – but for us, there’s another one – all our "common" functions are in a static class called, surprisingly enough, "commonFunctions"… These are the truly miscellaneous functions that in most cases are just "adding" a method or two to an existing class.

    For example, I HATE duplicated code. It really offends me to see if (instr(theString, searchString)>-1)… I would love to see if (theString.Contains( searchString)) – but as I have no way of adding Contains to String, I go for the lesser evil and create a StringContains( x, y) – so you have if (StringContains( x, y)) {…

    == readability ==

    So – what is more readable? (Ignoring the fact the function itself wouldn’t actually work as written :))

    public bool IsPersonalStatement( string theStatement )


    CommonFunctions.EnsureNotMissing( "theStatement", theStatement );

    return CommonFunctions.StringContains( theStatement, "my") || CommonFunctions.StringContains( theStatement, "I");



    public bool IsPersonalStatement( string theStatement )


    EnsureNotMissing( "theStatement", theStatement );

    return StringContains( theStatement, "my") || StringContains( theStatement, "I");


    I don’t believe there is ANYONE out there who would more quickly comprehend the first version.

    == context ==


    You MAY come back and say "ahh" but we don’t know what object those functions are coming from.. Well… there are a few obvious points:

    a) would it make any difference to you to know that it comes from an object called CommonFunctions instead of StringFunctions?? Would it help or hinder your understanding? I’ll go with hinder!

    b) if you really want to know, you can right click, and say go to definition

    c) by fully qualifying the paths, you run into the same stupid restrictions that the horrible hateful hungarian provided for us – that is – you can’t MOVE the functions. Suppose I one day want to clean up my codespace, and decide I have enough string functions to justify a StringFunctions static class. I just want to move the function – I don’t want to have to change every use of it anywhere – I just want to add using clauses.

    d) I’m with McConnell – almost always maintainable code == information hiding. The more information you hide, the stronger the system. I DON’T WANT people caring about (or knowing?) WHERE the functionality is coming from – I just want them to know it’s out there, and to use it. Especially when someone is reading it, I don’t want them READING the source of the function – when you read the above two functions, having the idea that StringContains comes from a library called CommonFunctions can ONLY slow your comprehension of the function – because you have to understand two concepts. It is blatantly obvious what StringContains does, and is something that your mind can follow easily. CommonFunctions.StringContains gets you thinking.

    e) "Overloading"

    I want to see a function like this

    blah Best( blah [] theSetOfBlahs )


    blah theBestValue = SafeFirstItem( theSetOfBlahs );

    foreach (blah toCheck in theSetOfBlahs)

    theBestValue = Min( toCheck, theBestValue );

    return bestValue;


    Now, if blah happens to start of life as an int – then the function above is fine, and Min is resolving to Math.Min. Suppose we then want to change it to type "ReallyBigInt"… well – Math doesn’t define a Min of ReallyBigInt. We always have to define a Min for ReallyBigInt’s, but why do we have to also change every function using it? I just want to USE my new ReallyBigMath library, and leave everything else exactly the same

    f) Consistency – people complain about using static functions, without qualifying them… but most function calls we do like that:


    class x

    public int Add( int a, int b ) {return a+b;}

    public void DoSomething() {Console.Writeline( Convert.ToString( Add(5,2)));}

    We are calling Add without qualifying it!! (Some people use this. for everything, which I admire for it’s consistency – but I definitely wouldn’t hire them :))

    == specific usage ==

    When would I use it? I have about two classes I’d ever use it for.. They are: CommonFunctions and Assertion. The trouble is, every single class I write in the system, without exception, calls at least something in commonFunctions (if only EnsureNotMissing). And surprisingly enough, every single test I’ve ever written includes an assertion! So the impact of being able to do this is HUGE..


    AssertEquals( "check there were 20 people", 20, numberPeople );


    Assertion.AssertEquals( "check there were 20 people", 20, numberPeople );

    Does the word assertion add anything? NO.

    Does it take anything away? YES… Because we have our own assertions… so we have the lines

    Assertion.AssertEquals( "check there were 20 people", 20, numberPeople );

    SMBAssertion.AssertPageTitleContains( "Check we are on the entry page", "Employee details" );

    How crap is that? If we could add methods to Assertion it would be all fine, but… we can’t..

    == conflicts ==

    OK – so, the case for needing this is pretty obvious. Then people come up with the technical issue – what about namespace conflicts – how do you resolve it?

    Well… we can have conflicts at the moment – define the same class in two different namespaces and you have a conflict. Make a method the same name as a class, and you have a conflict. You would resolve these in exactly the same way – and if people have a conflict, they just have to fully qualify the names..


    When it comes down to it, if you use two static classes with a method called Process (in fact lets face it… if you make a method called Process) – then you deserve EVERYTHING you get!! I can tell you the two static classes I would directly "use"…. and I can state, with absolute confidence, that I will NEVER get a name conflict with any methods in them!

    == choice ==

    But when it comes down to it, the biggest reason we should be able to directly "use" static classes is choice. If you don’t want to use this feature, then DON’T. Having it in the language doesn’t affect you in the slightest. I very much DO want the syntax, even though only for two classes. It affects me, because I want to use it – it doesn’t affect you, because you don’t… so why do you care? Yes it can be abused.. but that’s what code standards are for.

  10. Darren Oakey says:

    oooo – and I just thought of one other thing…

    Absolutely ANY argument saying this is bad:

    > using Math;

    > …

    > x = Sin(23);

    applies EQUALLY well to this scenario:

    > using System.Drawing;

    > …

    > Color baseColor = Color.Red;

    If you accept that "using" a static class is bad, you MUST also accept that "using" a namespace is bad – because in every way you are doing the same thing… so really you should be writing

    > System.Drawing.Color baseColor = System.Drawing.Color.Red;

    Now some people probably wouldn’t be horrified by that – but I am!

    I believe this whole argument comes down to the slow religions conversion of people into OO.. remember – OO is useful in some situations – but it IS NOT the only tool, and in a lot of cases it IS NOT the BEST tool. Functional programming and structured programming very much still have their place in today’s languages – and both provide no particular requirement for a function to "belong" to something. Making decisions based on religious zealotry is a bad thing! 🙂

  11. John Rusk says:


    I agree with you that readability is poor with things like these:




    The best work-around that I’ve found in my own code is to set things up like this:



    >Assert.Equals(…) (OK, I copied this one from NUnit)

    On one hand this is an ugly hack. On the other hand it’s the middle ground between the two opposing views on this subject.

    I like your excellent explaination of the "pro static import" view (even though Eric’s post has persuaded me to sit on the fence on this issue myself!). By the way, you wrote that there’s no difference between using a static class and using a namespace. There is one slight difference…

    Regardless of whether you see

    > …Color.Red



    you always know that Red is something defined outside of the class you’re current reading.

    Compare that to




    In the latter you have lost the clear hint that Sin is "outside the current class". It could be a method on the class you’re reading, or it might not. So static class imports create a bit more ambiguity than namespace imports, which I think was Eric’s point. On the other hand, maybe that extra ambiguity is a price worth paying in some circumstances, as you suggest.


  12. Lee says:

    "If you accept that "using" a static class is bad, you MUST also accept that "using" a namespace is bad – because in every way you are doing the same thing… so really you should be writing "

    That was more my point with the example I gave. Why are static imports bad, but shortcutting namespaces ok?

  13. Daniel O'Connell says:

    I don’t like this concept as it stands, I think it creates confusion. However I can suggest a different solution using the new namespace resolution operator. It wouldn’t be so bad to be able to write something like

    using static Math;

    using static BigIntegerMath;

    int x;

    BigInt y;



    what have you or to allow syntax that aggregates static functions into a single, named namespace. (Note I don’t use = here because that suggests single assignment).

    using static System.Math -> Math;

    using static BigInteger.Math -> Math;

    int x;

    BigInt y;



    Something that explicitly shows what you are doing while avoiding the problems of type replacement, make it clearer that you are importing a classes members, not a namespace, and perhaps a few other minor issues that I havn’t thought of yet. Most importantly it would make it easy to simulate static class aggregation. There would be rules to deal with, conflicting overloads etc may be a touch troublesome, but I don’t think it would be anything worse the conflict problems you face with direct static import or namespace importing.


  14. Justin says:

    One possible solution to the problem of not being able to distinguish external methods, would be for the IDE to support different coloring for internal vs. external members.

  15. Darren, on c) you should use refactoring. On e), you should use generics.

    Daniel, using can be used to define shortcuts, like this:

    using BigInteger.Math = BigMath;

  16. This is all pretty ridiculous IMO. I’m pretyt much in the Darren camp on this one.

    However, the reason we have tehse problems is because we have statics!! Why can’t I just do.


    instead of



    This was you get the best of all words. It’s brief. It’s OO. You can have virtual implementations which means you can change the type of x in teh future and still have this work.

    Why dont’ we stop introducing so much static junk into the framworks and instead put them where they belong and thus eliminate this entire problem altogether?

  17. Daniel Schlößer says:

    Would it be more productive, to put the decision whether a class’ static members are automatically imported in current scope in its declaration? Like this:

    class autoimport CommonFunctions {

    static public int Foo(){}


    So when you habe "using CommonFunctions" you have access to all static members without fully qualifying them. One could do that as well in the static function declaration as well.

  18. Laura T. says:

    In certain situations I’m in favor of static systems, isolated. In many cases I do not want inteference of any kind (think of hospital systems. A security bug fix should, must, not break anything. But I still need to update the system for other things. It’s always a risk). The world is dynamic, but there are static forces around there.

    As for syntax, I think <initiator>.<action> is less ambiguous. Many people event prepend this. even when it is implicit. I think it’s a good pratctice and also less error-prone. So int p=Process() leaves the doubt if the Process() is of this. object or something from other assemblies (from using keyword). Compiler could catch ambiguous functions, but it’s not 100% secure (polymorphic functions). I agree that using keyword is bad, but sometimes you need a shorthand to be more productive. I’d like to have an option that I must prepend the <initiator> (at least one) before the <action>, like System.Diagnostics.Debug.WriteLine would become Debug.WriteLine (and not WriteLine only).

  19. Some thoughts on static imports and other stuff…

Skip to main content