28

I wanted to ask what is the idea behind the fact that System.String doesn't contain parameterless constructor.

Because of this you cannot use this type when there is new() constraint.

UPDATE

Why do you think that new string() is useless and e.g. new int() is not useless. I really cannot see the difference. I really would like to be able to use a new() constraint on string, since what I'm expecting is String.Empty.

UPDATE2

I know that int is a value type and all value types have default parameterless constructor. I was referring to @John Saunders answer (and similar answers) that were stating that saying new String() basically doesn't do anything useful. So if new String() doesn't mean anything useful what is so useful about new int()? I also understand that it is important for value types to have default parameterless constructors. What is more I think that it would be really nice for string to have a default parameterless constructor. Lack of a parameterless constructor means for me that an object simply cannot exist without a parameter that will initialize it. In my opinion string doesn't need any parameter because it could be empty. I asked this question because I wanted to know if there is some important reason for string not having parameterless constructor or it's just design or sth else.

UPDATE3

I guess it will be the last update since it looks more like a blog post than a question. In java strings are also immutable and new String() is perfectly legal. However, documentation for parameterless constructor says:

Initializes a newly created String object so that it represents an empty character sequence. Note that use of this constructor is unnecessary since Strings are immutable.

UPDATE4

Ok, last update ;) I have to agree with John Saunders. I was using code that had new() constraint and it worked nicely for custom classes. Then, my colleague need to change the code for ints and it was ok. Then change it for string and we had a problem. When I now think about it I guess the code we are using needs to be changed to reflect that we need scalar types not classes that have parameterless constructor. All that said, I still think it's a bit inconsisent that you can write new int() and you are unable to write new string() (yes, I understand that int is a value type ;)). Thanks for all your answers!

Thanks in advance for help.

6
  • Added tag "contraints" because that's the heart of the problem. Commented Mar 16, 2010 at 14:37
  • Can you print your source code for the use case where you need the string to be passed into a generic method with the "new" constraint. I think that might clear things up. Commented Mar 16, 2010 at 16:01
  • Its not just the new constraint, but a default constructor also makes it easier to create empty instances of strings with reflection. Commented Mar 16, 2010 at 16:37
  • I'd say this is a design decision by the CLR team that needs to be answered by one of them, or someone who knows their reasoning behind it. My guess would be they don't want you to think a string is a reference type that, as John Saunders said, can be acted upon as if it's an instance reference. Commented Mar 16, 2010 at 18:16
  • @empi: Please show me what you would do with such an empty string either in a Reflection or a Generic context. I can't think of any value to such an empty string. BTW, I didn't mean the constructor was useless - I meant the resulting string would be useless. Commented Mar 16, 2010 at 19:27

11 Answers 11

25

If you could use

string s = new string();

What would you do with it? Strings are immutable.


Some readers have thought I was saying that a parameterless string constructor would be useless. That's not what I meant. I meant that the empty string created from such a constructor would be useless in the rest of the code.

Keep in mind what the OP said he wanted to do:

public void SomeMethod<T>() where T : new()
{
    var t = new T();
    // Do _what_ now?
}

// Call:
SomeMethod<string>();

I don't see what you could do with t after it was constructed.

Sign up to request clarification or add additional context in comments.

22 Comments

So you never use String.Empty then?
@Joe Gauterin - I don't think Saunders is saying anything about String.Empty. He is saying that it doesn't make sense to have a parameterless constructor for the string class. Either you set a default value, string.empty, or null.
@John: new String() should reasonably return String.Empty. I've been burned several times because I wanted to pass a string into a generic method DoSomething<T>(T t) where T : new(), but I can't work with strings because they don't have a default constructor.
@JonH: Clearly it does make sense to have a parameterless constructor, as the questioner has a use case for one. It doesn't help that the default value all class types is null, not String.Empty.
@Joren: no, it's the answer. it doesn't have a parameterless constructor because it wouldn't make any sense in an immutable type.
|
11

Why do you think that new string() is useless and e.g. new int() is not useless.

Let's go back to basics and talk about reference and value types.

When you create an int, long, point, or whatever, the value type is allocated on the stack -- so an int reserves 4 bytes on the stack, long is 8 bytes, and so on. The stack space reserved for the value type is zero'd out -- its not possible ever to refer to value types address on the stack and get a null. So default constructors on value types probably result more from quirks in stack allocation than usefulness (maybe someone at MS could give more insight).

In any case, I think System.String lacks a default constructor because of lousy API design.

Immutable objects -- enumerables in particular -- almost always expose a default constructor to instantiate an empty collection.

I think Microsoft had good intentions: it is better to use "" or String.Empty whenever you need an empty string because they're interned, and not so useful to new up a new String() everytime -- but it comes across to me as Microsoft's way of "saving the developers from themselves".

(Thanks Microsoft, I appreciate your paternalistic hand-holding, but I'm perfectly capable of taking care of myself. If I don't want to create multiple instances of the same object, I'll cache it just like I do for the bagillion other types with a default constructor.)

For now, you need to treat objects without default constructors as a special case from everything else. Rewrite

public void DoSomething<T>() where T : new() { ... }

As two methods:

public void DoSomething<T>() where T : new() { DoSomething(() => new T()); }

public void DoSomething<T>(Func<T> constructor) { }

Clients to your code should decide which function to call for themselves.


Now someone looking at the code above might ask why you'd pass a constructor instead of an actual object into the method, i.e.

public void DoSomething<T>(T obj) { ... }

There might be reasons, for example if the constructor method isn't guaranteed to be called. I worked complex winform app where clicking buttons or menu items would pop up a form -- or, if the form was already open, we'd focus it instead. So we had something like:

public T ShowForm<T>(Func<T> constructor) where T : Form
{
    T res = default(T);
    foreach(Form f in Application.OpenForms)
    {
        if (f is T)
        {
            res = (T)f;
            break;
        }
    }

    if (res == null)
        res = constructor();

    res.Focus();
    return res;
}

We couldn't use the new constraint since some forms had non-default constructors, so the strategy above ultimately worked out really well and saved us the trouble of creating a ton of factory classes.

2 Comments

+1, nice solution. However, it works only if T is a type paramter for a generic method, not for a generic class
You can certainly use it for generic classes: DoSomething(() => new List<int>());
4

I'm guessing you want to be able to define a class that's something like this:

public class SpecializedCollection<T> where T : new() {
    private List<T> _startingItems;

    public SpecializedCollection(int startingSize) {
        _startingItems = new List<T>(startingSize);
        for (int i = 0; i < startingSize; ++i)
            _startingItems.Add(new T());
    }

    // ... lots more code
}

Am I right? If you want this to be more flexible, to allow for types that may not have a default parameterless constructor, you can always do this:

public class SpecializedCollection<T> {
    private List<T> _startingItems;

    // note: here we leave it up to the caller to specify
    // how T objects will be instantiated
    public SpecializedCollection(int startingSize, Func<T> generator) {
        _startingItems = new List<T>(startingSize);
        for (int i = 0; i < startingSize; ++i)
            _startingItems.Add(generator.Invoke());
    }
}

Then you could create a SpecializedCollection<string> like so:

var strings = new SpecializedCollection<string>(10, () => string.Empty);

Of course, if you wanted to offer a default constructor that would attempt to construct objects using a parameterless constructor for T, you could always overload the constructor:

public SpecializedCollection(int startingSize)
    : this(startingSize, Activator.CreateInstance<T>()) { }

The above wouldn't work for string, of course, but it would for any class with a parameterless constructor (i.e., anything that would've worked with the old where T : new() constraint).

Comments

3

What is a string without an actual string?

You can do this:

  String s = "hello world";

And once you have the string you cannot alter that specific string (strimgs are immutable). If you are looking to declare an empty string then just do:

string s = string.empty

Comments

2

It's a common problem in generic code. C++ solves it with template specialization, but C# doesn't support that.

It can't be done cleanly in C# though - your best bet is to use the class constraint instead, then use reflection based hack to default construct a T or use String.Empty if T is System.String. You'll lose compiler checking for using other classes which aren't default constructable though.

Here's another option:

class MyClass<T> where T : class
{
    public MyClass(T default)
    private T m_default;      
};

MyClass<object> instance = new MyClass<object>(new object());
MyClass<string> instance = new MyClass<string>(String.Empty);

And another:

class MyClass<T> where T : class
{
    static SetDefault(T def)
    { 
       s_default = def;
    }
    static T s_default;      
};

MyClass<object> instance = new MyClass<object>(new object());
MyClass<string> instance = new MyClass<string>(String.Empty);

Comments

1

"[Why doesn't] System.String...contain [a] parameterless constructor?"

Because that's the way it was designed. As you can see from the variety of answers and opinions here, there's not even a clear consensus on the need or implementation of a parameterless constructor. Obviously, it's technically possible to have a default constructor that initializes to String.Empty - so either the BCL team didn't think of it (unlikely), or didn't feel it was a worthwhile scenario (likely). FWIW, I agree - I don't see a reason why a default ctor on string is important.

"Why do you think that new string() is useless and e.g. new int() is not useless. I really cannot see the difference."

The difference is that int is a ValueType. ValueTypes are required to have a default constructor, and it initializes the type to a default value. string is a reference type - it already has a default value - null (the same as all other reference types).

Of course, you disagree - you have a specific scenario that you feel is best implemented with a default ctor on string. Without knowing specifics about your scenario, it's hard to comment on it intelligently. But, my guess is that you're dealing with primitive obsession. If string.Empty makes sense for your particular data, then you should probably have a class around it. It's default constructor can initialize a string.Empty.

E: Why primitive obsession?

I was going to write about ORMs or other mappers (the few places that I can think of that where T:new() is useful) and how, instead of trying to map strings, you should be using a custom business object. But, after doing some example code - I'm pretty stuck. I can't think of any scenario that makes sense with a new string() == string.Empty.

4 Comments

Primitive obsession means you create a method like PersistCustomer(customerId, customerFirstName, customerLastName, customerPhone) instead of PersistCustomer(customer). I don't think default constructors on objects counts as primitive obsession.
@Juliet - Yes, that is an example of primitive obsession - thanks. ;) The larger picture is that you're trying to force meaning onto primitives (oh look, it's an int named customerId - must be a reference to a customer!). I'll update with a bit more on why I'm guessing the OP is doing that...(note, though - that it is a guess. I have no knowledge of why he wants a default ctor)
Since value types are required to have default constructors, why not require String to have a default constructor? What you present just isn't a good argument.
@ThomasEding - AFAIK, ValueTypes are required to have an implicit default ctor for technical reasons, not for your convenience. I didn't mean to imply that MS requires default ctors so that you can use them in a new constraint. It just happens to work out that way, which is sometimes useful, sometimes not.
1

Specifically addressing how to avoid the new() constraint problem when you're working with generic types:

Include the following field, property, and method:

private readonly Func<T> _defaultValueFactory = (Func<T>)DefaultT;
private Func<T> DefaultValueFactory
{
    get
    {
        return _defaultValueFactory;
    }
}

private static T DefaultT()
{
    return default(T);
}

Also include a constructor for your type that takes a Func<T> defaultValueFactory.

Wherever you normally use new T(), use DefaultValueFactory() instead.

Comments

0

All empty Strings are the same. Why do you want to create one? You can use String.Empty or simply "".

Comments

0

From http://msdn.microsoft.com/en-gb/library/system.string.aspx

A String object is called immutable (read-only) because its value cannot be modified once it has been created. Methods that appear to modify a String object actually return a new String object that contains the modification. If it is necessary to modify the actual contents of a string-like object, use the System.Text.StringBuilder class.

So a parameterless constructor wouldn't make sense.

4 Comments

Immutability doesn't at all imply that an object shouldn't have a parameterless constructors. Case in point: every value type is immutable and has a parameterless constructor (i.e. DateTime d = new DateTime()), and every many implementations of immutable data structures will represent an empty node with a parameterless constructor.
Yep - value types are required to be both immutable and to have a parameterless constructor.
Value types are not immutable. If you create a struct you can change it's properties (struct Foo { public int bar; } Foo foo = new Foo(); foo.bar = 1; foo.bar = 2; ...). This is not possible for strings. Properties that return a value are immutable however as changing the returned value does not affect the original value as only a copy is returned from the property.
@dbemerlin: you can make a mutable value type, but almost everyone agrees they're evil and use of them in any serious production code is grounds for flogging.
-1

What would

String s = new String();

give you over

String s = String.Empty;

or

String s = null;

3 Comments

Why would new'ing up an instance of an object ever give you a null?
@Juliet - if the object is a ref. type and belongs to a class it defaults to null.
@Juliet, I realise I wan't being clear. What I meant was if you don't have anything to pass to the constructor then you probably want it to be either empty, or null.
-1

Int32 is a struct. Structs ALWAYS have a parameterless constructor. It has nothing to do with it's usefulness - even if Microsoft decided that Int32's parameterless constructor is completely and utterly useless, there is absolutely nothing they could do about it. And if they wanted to change the behavior of structs now, it would be a huge breaking change. Turning Int32 into a class is also not feasible at all as there is a reason why .net supports both Value and Reference type (I hear from the Java guys that the fact that Integer is a class causes some problems, but I can't comment on that really).

String on the other hand is a class. For classes, you can control whether or not is has a parameterless constructor, so here it was possible to see that it's useless and omit it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.