newb generic ?: How to cast reference to type parameter

S

sklett

I'm revisiting an old series of overloaded methods I have and I would like
to convert them to a single generic method. Here is the method in it's
current, overloaded implementation:
<code>
public StringCustomFieldRef GetStringField(string fieldID, CustomRecord
record)
{
if(record.customFieldList == null)
{
return null;
}

foreach(CustomFieldRef fieldRef in record.customFieldList)
{
if(fieldRef is StringCustomFieldRef &&
((StringCustomFieldRef)fieldRef).internalId == fieldID)
{
return fieldRef as StringCustomFieldRef;
}
}

return null;
}
</code>

I then tried to change it like so:
<code>
public TFieldType GetStringField<TFieldType>(string fieldID, CustomRecord
record)
{
if (record.customFieldList == null)
{
return default(TFieldType);
}

foreach (CustomFieldRef fieldRef in record.customFieldList)
{
if (fieldRef is TFieldType && ((TFieldType)fieldRef).internalId ==
fieldID)
{
return (TFieldType)fieldRef;
}
}

return default(TFieldType);
}
</code>

The above code throws to compiler errors that have me stumped:
"Cannot convert type 'PMDOutAddin.com.netsuite.webservices.CustomFieldRef'
to 'TFieldType'"

It could be that what I'm trying to do isn't possible, like I said, I'm very
new to generics. I've seen generic classes before that have something like
" : where ClassName" after them, it looks like it's a base class of
interface requirement. Maybe something like this on a method would be
needed?

Any suggestions welcome.
Thanks for reading,
Steve
 
J

Jon Skeet [C# MVP]

It could be that what I'm trying to do isn't possible, like I said, I'm very
new to generics. I've seen generic classes before that have something like
" : where ClassName" after them, it looks like it's a base class of
interface requirement. Maybe something like this on a method would be
needed?

You'll need some kind of constraint so that the internalId member is
available. I'm not immediately sure why it's complaining in quite the
way it is though - could you come up with a short but complete program
that demonstrates the problem, and we can take it from there?

See http://pobox.com/~skeet/csharp/complete.html for what I mean by
that.

Jon
 
C

Christof Nordiek

Hi Steve,

My Question would be, how the types CustomFieldRef and StringCustomFieldRef
(and other types, for wich there is an overload) relate to one another.
Does StringCustomFieldRef derive from CustomFieldRef (and do the other types
also)?
If so, a first step could be to add a type constraint.

public TFieldType GetStringField<TFieldType>(string fieldID, CustomRecord
record) where TFieldType : CustomFieldRef
{
...
}

This ensures, that TFieldType is a class deriving from CustomFieldRef and
the cast is possible.

Then still remains the problem of internalId. This property (or field?)
seems be defined in the deriving classes. If you can change the definition
of that classes, you should try to move it into the common base class.
Atleast there should be an abstract or virtual declaration of it, and maybe
overrides in the derived classes.
If that's not possible, you would be bound to use reflection, but that vere
likely will be worse, than having seperate declarations for each type.

HTH
Christof
 
S

sklett

Hi Christof,

The constraint is what I was looking for, thanks. I'm not able to change
the implementation of CustomFieldRef, but I can suggest the modification to
the developer(s) of the Web Service that it is generated from.

You are correct, StringCustomFieldRef inherits from the abstract base
CustomFieldRef

Thank you for your suggestion,
Steve
 
S

sklett

Thank you for the reply Jon,

where TType : Base/Interface is what I was looking for. Learn something
every day :)

Take care,
Steve
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top