Best Practice discussion: Difference between SWITCH and IF/ELSE-IF/ELSE?
Switch, like the if statement, is a tool. If can do whatever switch can do and more, but it can't do what switch does as efficiently as it does. Switch can drastically reduce the complexity of some code. Just to make a point, I'm going to show you a practical, very meaningful difference.
Schema.DisplayType someType = someField.getDescribe().getType();
if( someType == DisplayType.address || someType == DisplayType.Combobox || someType == DisplayType.Email ||
someType == DisplayType.EncryptedString || someType == DisplayType.MultiPicklist ||
someType == DisplayType.Phone || someType == DisplayType.Picklist || someType == DisplayType.String ||
someType == DisplayType.TextArea || someType == DisplayType.URL) {
// process as a string
} else if(someType == DisplayType.Date) {
//now a date
} else if(someType == DisplayType.DateTime) {
// date time
} else if(someType == DisplayType.Time) {
// time value
} else if(someType == DisplayType.base64) {
// binary data
} else if(someType == DisplayTYpe.Currency || someType == DisplayType.Double || someType == DisplayType.Integer) {
// Do something with numbers
} else {
// Id or DataCategoryGroupReference or Reference
}
switch on someField.getDescribe().getType() {
when ADDRESS, COMBOBOX, EMAIL, ENCRYPTEDSTRING, MULTIPICKLIST, PHONE,
PICKLIST, STRING, TEXTAREA, URL {
// process as a string
}
when DATE {
// process as a date
}
when DATETIME {
// process as a date time
}
when TIME {
// process as a time
}
when BASE64 {
// binary data
}
when CURRENCY, DOUBLE, INTEGER {
// Do something with numbers
}
when ID, DATACATEGORYGROUPREFERENCE, REFERENCE {
// Id or DataCategoryGroupReference or Reference
}
}
According to my text editor, the first code example is 915 characters, while the second is 541 characters (counting all comments and white space as tabs).
The first one is an unwieldy mess, the second one is actually quite legible, having removed 18 copies of someType == DisplayType.
from the code.
Aside from that, switch comes with a few built-in safety features:
If you forget a {
or }
, the compiler will let you know. Especially if you're in a hurry and/or tend to forget them:
if(cond1) {
method1();
method2();
} else if(cond2)
method3();
method4();
Another thing, switch was purpose built for dynamic sObject use. Before we'd have to write:
sObject someRecord = someMap.get(recordId);
sObjectType recordObjectType = someRecord.getSObjectType();
if(recordObjectType == Account.sObjectTYpe) {
Account accRecord = (Account)someRecord;
// ...
} else if(recordObjectType == Contact.sObjectType) {
Contact conRecord = (Contact)someRecord;
// ...
} // ...
Now, we have a much more elegant:
switch on someRecord {
when Account accRecord {
// ...
}
when Contact conRecord {
// ...
}
// ...
}
As you've noted, switch has particular limitations (this is actually the first release of it, future enhancements are being considered); the feature was shipped with minimal functionality based on what salesforce.com felt they could deliver on time for the most common use cases.
When you need to compare a single variable to a variety of different conditions, switch is probably the right tool to use. For everything else, there's if-else-if-else chains.
Note that TriggerOperation is specifically designed to take advantage of switch.
If else method:
if(Trigger.isInsert) {
if(Trigger.isBefore) {
//
} else {
//
}
} else if(Trigger.isUpdate) {
if(Trigger.isBefore) {
//
} else {
//
}
}
switch on Trigger.operationType {
when BEFORE_INSERT {
//
}
when AFTER_INSERT {
//
}
when BEFORE_UPDATE {
//
}
when AFTER_UPDATE {
//
}
}
This common use case was one of the intended purposes of switch; it removes the "need" to have unnecessarily nested if statements. Of course, this also depends on your specific trigger framework format, but for most people, it's simply less code, more legible.
For many practical cases, if statements will continue to be used as they are today. If statements are very practical in many cases, and switch isn't here to replace if. However, the moment you need to compare one value to many different possible values, switch is often more attractive and makes more legible code.
For what its worth, there is also a roughly 10% improved performance using switch over using an exceptionally large if-else chain. For if-else chains that are large enough to be a significant reduction in code, they will also represent a modest boost in performance as well.
I don't know why you'd want to do this, but you could choose to use a "boolean":
Boolean flag = ...;
switch on String.valueOf(flag) {
when 'true' {
System.debug('Flag is set.');
}
when 'false' {
System.debug('Flag is unset.');
}
}
I can't think of a practical reason for doing this, but this code demonstrates that it's at least possible to do that (but it's one line less efficient than if-else chaining). Also, there may be other practical uses you haven't thought of yet. I understand it's a different bit of code than what you're used to, but it certainly has many practical applications; the larger your if-else chain, the more likely it is that switch can help you declutter and organize your code.
So, at the end of the day, you won't be using switch every day, and nobody's forcing you to change, but switch is there when you have a specific problem that needs to be solved.
The accepted answer here Looping over a list of sObjects that has more than object type shows an Apex-specific extra capability of type matching that is kinda neat.
Personally I'd rate a library feature like Comparator support above a language feature switch
, but as I understand it, this was something of a test case to demonstrate that language enhancements can actually be delivered after years of stagnation. Lets hope that more substantial language enhancements are on the way e.g. generics.