3

Can I create a generic method that accept two types. The attributeType and ts_attributeType do not share any common parent class although they do have the same fields.

Is this possible? Or is there some way I can achieve this?

private static void FieldWriter<T>(T row)
        where T : attributeType, ts_attributeType

    {
        Console.Write(((T)row).id + "/" + (((T)row).type ?? "NULL") + "/");
    }

I have seen this answer from Jon Skeet, however I am not certain if it also applies to my question.

Some further background: Both attributeType and ts_attributeType have been created using the xsd.exe tool; and are are partial classes.

Community
  • 1
  • 1
Ahmad
  • 22,657
  • 9
  • 52
  • 84

3 Answers3

7

No, you can't. The simplest alternative is to simply write two overloads, one for each type. You can always extract the common code if you want to avoid repeating yourself too much:

private static void FieldWriter(attributeType row)
{
    FieldWriterImpl(row.id, row.type);
}

private static void FieldWriter(ts_attributeType row)
{
    FieldWriterImpl(row.id, row.type);
}

// Adjust parameter types appropriately
private static void FieldWriterImpl(int id, string type)
{
    Console.Write(id + "/" + (type ?? "NULL") + "/");
}

Alternatively, you could use dynamic typing if you're using C# 4.

(A better solution would be to give the two classes a common interface if you possibly can - and rename them to follow .NET naming conventions at the same time :)

EDIT: Now that we've seen you can use partial classes, you don't need it to be generic at all:

private static void FieldWriter(IAttributeRow row)
{
    Console.Write(row.id + "/" + (row.type ?? "NULL") + "/");
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thanks Jon, so is my current solution is correct a good approach? – Ahmad Aug 05 '11 at 09:18
  • @Ahmad: Yes, using partial classes to implement a common interface is a good solution, and one I've used elsewhere. I wouldn't call it `ICommonFields` though, given that it doesn't specify *fields* :) It also doesn't need to be generic - will edit my answer. – Jon Skeet Aug 05 '11 at 09:20
  • I missed that in my original solution. There was no need to have a generic constraint. Thanks – Ahmad Aug 05 '11 at 09:26
1

My current solution involves creating an interface and letting the partial classes implement it. Slightly backwards in logic.

namespace Test
{
    public partial  class attributeType: IAttributeRow {}

    public partial class ts_attributeType : IAttributeRow {}

    public interface ICommonFields
    {
        string id { get; set; }
        string type { get; set; }
    }
}


    private static void FieldInfo<T>(T row)
        where T : IAttributeRow 

    {
        Console.Write(((T)row).id + "/" + (((T)row).type ?? "NULL") + "/");
    }
Ahmad
  • 22,657
  • 9
  • 52
  • 84
1

If they are partial classes, and both have the same properties, you could extract those properties into an interface and use that as your generic constraint.

public interface IAttributeType
{
   int id{get;}
   string type{get;set;}
}

Then create a partial class matching your 2 classes, and simply implement the interface:

public partial class AttributeType : IAttributeType
{
  // no need to do anything here, as long as AttributeType has id and type
}
public partial class ts_AttributeType : IAttributeType
{
  // no need to do anything here, as long as ts_AttributeType has idand type
}

Now you can constrain the generic by the interface:

private static void FieldWriter<T>(T row)
    where T : IAttributeType

{
    Console.Write(row.id + "/" + (row.type ?? "NULL") + "/");
}
Jamiec
  • 133,658
  • 13
  • 134
  • 193
  • This is especially useful when dealing with linq2sql generated classes that all return the same table data where there is no practical way to give them a common base class. – Nick Van Brunt Jul 22 '16 at 13:15