As many others have said, switch statements must be compile time constants as explained in the C# language specification (found here: http://www.microsoft.com/en-us/download/details.aspx?id=7029) in section 8.7.2:
A switch-statement consists of the keyword switch, followed by a
parenthesized expression (called the switch expression), followed by a
switch-block. The switch-block consists of zero or more
switch-sections, enclosed in braces. Each switch-section consists of
one or more switch-labels followed by a statement-list (§8.2.1). The
governing type of a switch statement is established by the switch
expression.
• If the type of the switch expression is sbyte, byte,
short, ushort, int, uint, long, ulong, bool, char, string, or an
enum-type, or if it is the nullable type corresponding to one of these
types, then that is the governing type of the switch statement.
• Otherwise, exactly one user-defined implicit conversion (§6.4) must
exist from the type of the switch expression to one of the following
possible governing types: sbyte, byte, short, ushort, int, uint, long,
ulong, char, string, or, a nullable type corresponding to one of
those types.
• Otherwise, if no such implicit conversion exists, or
if more than one such implicit conversion exists, a compile-time error
occurs.
The constant expression of each case label must denote a value
that is implicitly convertible (§6.1) to the governing type of the
switch statement. A compile-time error occurs if two or more case
labels in the same switch statement specify the same constant value.
With that in mind even if you could achieve this, it would be a code-smell at best. The primary reason for this is it would violate the Open/Closed principle (http://www.oodesign.com/open-close-principle.html) in that you would have to make modifications to this section of code as new types of U (whatever they are) are introduced. Consider this BAD example:
public enum ItemType : int {
Default = 0,
Basic = 1,
Advanced = 2,
Expert = 3
}
public class NotSoGoodItem {
public string Name { get; set; }
public int Id { get; set; }
public ItemType DataType { get; set; }
public List<String> BasicSettings {get; set;}
public List<String> AdvancedSettings {get; set;}
public List<String> ExperSettings {get; set;}
}
public static NotSoGoodItem CreateNewItem(ItemType item) {
//item is inherently an int
switch (item) {
case ItemType.Default | ItemType.Basic:
return new NotSoGoodItem() { Name = "Basic Item", BasicSettings = new List<String>() };
case ItemType.Advanced:
return new NotSoGoodItem() { Name = "Advanced Item", AdvancedSettings = new List<String>() };
case ItemType.Expert:
return new NotSoGoodItem() { Name = "Expert Item", AdvancedSettings = new List<String>() };
default:
return null;
}
}
In this case, the switch statement uses the enum value (which inherits from int and satisfies the specification requirement) to determine which property to fill and what values to set. This is problematic as if you wanted to introduce a new level or ItemType
of say, Guru, you would have to modify at least 3 code files to make this change (the enum, the NotSoGoodItem
to add the property, and the method that does the creation).
Instead by using generics, this code can be simplified using the following Good example:
public abstract class GoodItem {
protected GoodItem() { }
private string _name;
public virtual string Name { get { return string.Concat(Prefix, _name); } set { _name = value; } }
protected virtual string Prefix { get; set; }
public virtual int Id { get; set; }
public virtual List<String> Settings { get; set; }
}
public class BasicItem : GoodItem {
public BasicItem()
: base() {
Prefix = "Basic";
}
}
public class AdvancedItem : GoodItem {
public AdvancedItem()
: base() {
Prefix = "Advanced";
}
}
public class ExpertItem : GoodItem {
public ExpertItem()
: base() {
Prefix = "Expert";
}
}
public static T CreateNewItem<T>() where T : GoodItem {
return Activator.CreateInstance<T>();
}
With this approach, zero code files must be modified. All that needs to be done is to add a new type that inherits from GoodItem
.