Ray
Ray

Reputation: 4929

Can't understand C# Generics

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

Answers (5)

Ali Alavi
Ali Alavi

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

usr
usr

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

Joel Coehoorn
Joel Coehoorn

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

Tejs
Tejs

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

CrazyCasta
CrazyCasta

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

Related Questions