0

We're using the Enterprise WSDL to write a service that will be run from our server and sync data to Salesforce. We're using C# to do this.
I have several functions that perform SOAP operations on lists of generic sObjects such as

public void upsertSObjects(List<sObject> sobjs, string externalIdField){
    ...
}

My custom objects are defined properly in the class generated by the WSDL. For example:

public partial class MyCustomObject__c : sObject {
    ...
}

Following the rules of polymorphism, one would expect that I would be able to do the following:

List<MyCustomObject__c> myList = new List<MyCustomObject__c>();
//populate the list with records
upsertSObjects(myList, "ExtId__c");

However, I get a compilation error:

Argument 1: cannot convert from 'System.Collections.Generic.List<namespace.MyCustomObject__c>' to 'System.Collections.Generic.List<namespace.sObject>'

closed as off-topic by Daniel Ballinger, Raul, Himanshu, Markus Slabina, Dave Humm Sep 12 '17 at 11:00

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Programming questions not specific to Salesforce are off-topic here, but can be asked on Stack Overflow." – Daniel Ballinger, Raul, Himanshu, Markus Slabina, Dave Humm
If this question can be reworded to fit the rules in the help center, please edit the question.

  • I've voted to close this. It is a scenario specific to C# rather than Salesforce. – Daniel Ballinger Sep 12 '17 at 8:59
3

This is the in-variant vs co-variant scenario on Generic Lists. See Covariance and Contravariance in Generics.

That's the computer science explanation, but I find an example easier to work through.

Let's say C# did let you pass your List in to the upsertSObjects method like you proposed.

List<MyCustomObject__c> myList = new List<MyCustomObject__c>();
//populate the list with records
upsertSObjects(myList, "ExtId__c");

Now upsertSObjects has the sobjs argument that it thinks is a List<sObject>. That's all fine, unless the upsertSObjects tries to add something else to the sobjs List. Something that is or inherits from sObject but is not a MyCustomObject__c. Now we have a problem, because you can't do that to myList without breaking the generic type is is storing.

Because of that scenario C# will stop you at compile time.

A couple of possible solutions:

  1. Change the signature of upsertSObjects to public void upsertSObjects(IEnumerable<sObject> sobjs, string externalIdField){}. IEnumerable doesn't have an add/insert method so the problem goes away.
  2. Change myList to be a List<sObject>. Now the underlying type can old anything that inherits form it.

See also:

Not the answer you're looking for? Browse other questions tagged or ask your own question.