Reputation: 4929
I'm able to understand C# Generics but only when I read about it in a book where the examples are easy to follow. But in real life I get to see complicated C# Generics code like below. Can someone explain to me the generic aspects of this code? I see the type parameter but don't understand why the T is not used in the body of the method. How is the T being used in the body?
public void ValidateExceptionFromResponse<T>( BaseClaimResponseDataContract<T> response )
{
if (response.CommunicationResponseCodes != null && response.CommunicationResponseCodes.Any())
{
var validateResult = new ValidationResults();
foreach (var communicationResponseCodeDataContract in response.CommunicationResponseCodes)
{
validateResult.AddResult( new ValidationResult(communicationResponseCodeDataContract.Description.Current, null, null, null, null));
}
throw FaultManager.GenerateFault(validateResult);
}
if( response.MessageError != null )
{
throw FaultManager.GenerateFault(eErrorCodes.Claims, response.MessageError.Current);
}
}
Here is a snippet for BaseClaimResponseDataContract:
[KnownType(typeof(SummaryClaimsReportResponseDataContract))]
[KnownType(typeof(ClaimResponseDataContract))]
[KnownType(typeof(CommunicationResponseDataContract))]
[DataContract]
public class BaseClaimResponseDataContract<T>
{
[DataMember]
public bool IsRxClaim { get; set; }
[DataMember]
public ThirdPartyDataContract ThirdParty { get; set; }
[DataMember]
public ExternalSystemMessages RequestMessage { get; set; }
[DataMember]
public bool RequestAccepted { get; set; }
[DataMember]
public string ResponseStatus { get; set; }
[DataMember]
[StringLength(10)]
public string ResponseCodes { get; set; }
[DataMember]
public string[] ResponseCodesArray
{
get
{
var lstMessageCodes = new List<string>();
if (!string.IsNullOrEmpty(ResponseCodes))
{
for (int i = 0; i < ResponseCodes.Length / 2; i++)
{
var code = ResponseCodes.Substring(i*2, 2);
if (!string.IsNullOrWhiteSpace(code))
lstMessageCodes.Add(code);
}
}
return lstMessageCodes.ToArray();
}
}
[DataMember]
public IEnumerable<CommunicationResponseCodeDataContract> CommunicationResponseCodes;
[DataMember]
public StringDataContract MessageError { get; set; }
public void CopyFrom(BaseClaimResponseDataContract<T> claimResponse)
{
IsRxClaim = claimResponse.IsRxClaim;
ThirdParty = claimResponse.ThirdParty;
RequestMessage = claimResponse.RequestMessage;
RequestAccepted = claimResponse.RequestAccepted;
ResponseStatus = claimResponse.ResponseStatus;
ResponseCodes = claimResponse.ResponseCodes;
CommunicationResponseCodes = claimResponse.CommunicationResponseCodes;
MessageError = claimResponse.MessageError;
}
}
Upvotes: 2
Views: 618
Reputation: 2467
It doesn't matter whether T is used in the method or not. We can have a generic function like this:
int dummy<T> (List<T> a)
{
return a.Count * 2;
}
As you can see, T is not used anywhere in the method.Your example might also be something like this. Read on if you need more explanation: Look at it this way: you have a generic type, and you want to write a method which takes a parameter of such a type, here BaseClaimResponseDataContract<>. Now, you can either write different methods, each for a concrete instance of this type, e.g.
public void ValidateExceptionFromResponse( BaseClaimResponseDataContract<int> response )
{ ... }
public void ValidateExceptionFromResponse( BaseClaimResponseDataContract<float> response )
{ ... }
public void ValidateExceptionFromResponse( BaseClaimResponseDataContract<String> response )
{ ... }
which of course in not efficient, or let the method be a generic one, i.e. can take instances of BaseClaimResponseDataContract<> made from all types. Let's call this type T, then we can write
public void ValidateExceptionFromResponse<T>( BaseClaimResponseDataContract<T> response )
Upvotes: 0
Reputation: 171178
Usually, generics are used to conserve type information and flow it around. You get the same type out of a list that you put in.
In your case that is not apparent. T
seems to be unused except to close the generic type.
Maybe BaseClaimResponseDataContract<T>
has no useful non-generic base class. You can't use an open generic type, so you have to close it with a generic type parameter.
Upvotes: 0
Reputation: 415735
In the case, it's not the method so much that's generic: it's the argument. The method is generic simply so that it can accept a type that is generic. You don't need to use the T
argument within the method, because it's enough to know about the BaseClaimResponseDataContract
part.
Upvotes: 2
Reputation: 41236
In this situation, it seems the only purpose of the generic argument is to enforce that the parameter to the method must be a BaseClaimResponseDataContract<T>
. I suspect multiple types in your solution inherit from this, for example:
public class SomeSample : BaseClaimResponseDataContract<AnotherClass>
{
}
The method can only be called with instances that implement this base type, so it's like a form of marking classes with an interface.
Upvotes: 6
Reputation: 28302
The method was made generic because it takes a generic argument. In order to specify the type of the argument a generic is used which means the method much take a generic argument itself.
Upvotes: 2