5

I'm writing a generic DataStructure<T> which persists on the disk, and I need to write it such that T is guaranteed to be serializable in a fixed number of bytes. For example, int and char should be accepted, but string or int[] should not be. Likewise, a struct with a string member is not acceptable, but an unsafe struct with a fixed char array is.

I could write a runtime test in the initializer using reflection and sizeof to test each member, but that seems like a terrible hack. Is there any efficient and (relatively) safe way to do this?

dlras2
  • 8,416
  • 7
  • 51
  • 90
  • All T's are guaranteed to be fixed size (since every instance of a class has same size), your interpretation of string (for that matter any reference type) is what is the problem, you might have to add special case to handle all reference types by reflecting T. http://msdn.microsoft.com/en-us/library/b8ytshk6.aspx – Sanjeevakumar Hiremath Aug 11 '11 at 15:23
  • @Sanjeevakumar - You're technically right, my title was worded slightly incorrectly. I've updated it to better reflect my actual question. – dlras2 Aug 11 '11 at 15:26
  • 4
    Of course, for sufficienty large `n`, all data is serializable in `n` bytes :p kore seriously, are you sure you want fixed sized records? It is hugely limiting... – Marc Gravell Aug 11 '11 at 15:37
  • "If you have a small number of possibilities for the generic type argument then the method is not truly generic. The point of generics is to allow parameterization of types and methods so that you can create infinitely many different such types and methods on demand. If you only have three possible types then write three methods. That is, create overloads, don't use generics." - **(Eric Lippert)[http://stackoverflow.com/questions/2391968/c-generic-constraints]** - – Sanjeevakumar Hiremath Aug 11 '11 at 15:50
  • @Marc - I'm coming to the same realization. I'm now considering a simple fixed-sized index structure pointing to the classes serialized at the end of the file. (With protobuf-net, of course.) – dlras2 Aug 11 '11 at 15:52
  • @Sanjeevakumar - There are indeed an infinite number of fixed-sized `struct`s. – dlras2 Aug 11 '11 at 15:54

2 Answers2

5

There is no way to statically support a generic parameter which only have a fixed specific size. Constraints are limited to interfaces, ref / struct, base class and new.

What you can do though is use static factory methods to limit the uses of the generic to a known finite set of types which are suitable. For example

class DataStructure<T> { 
  private DataStructure(T value) { 
    ...
  }
}
static class DataStructure { 
  public static DataStructure<int> Create(int i) { 
    return new DataStructure<int>(i); 
  }
  public static DataStructure<char> Create(char c) { 
    return new DataStructure<char>(c); 
  }
}

This is limiting though because it requires you to list all comparable types ahead of time. If you want a more flexible solution that works with user defined types you'll need to implement a runtime check.

public static DataStructure<T> Create<T>(T value) { 
  RuntimeVerification(typeof(T));
  return new DataStructure<T>(value);
}
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • This is not a generic implementation. – Sanjeevakumar Hiremath Aug 11 '11 at 15:25
  • @Sanjeevakumar the OP did not specifically call for one. There post already indicates they're aware of how to do it they just wanted ot know if there was a better way (and there's not). – JaredPar Aug 11 '11 at 15:26
  • I don't think that will work in this situation, as the point is to support user defined types, but it's an interesting factory pattern I hadn't thought of before. +1 – dlras2 Aug 11 '11 at 15:27
  • 3
    For the best of both worlds, `public static Create(T obj)` could implement the runtime check for unrecognized types. – Chris Shouts Aug 11 '11 at 15:28
  • @Dan if you need to support user defined types then I think you're forced into a runtime check. Just no way to avoid it. – JaredPar Aug 11 '11 at 15:28
  • @Chris agreed, went ahead and added that to the answer. – JaredPar Aug 11 '11 at 15:31
1

Every valuetype that directly or indirectly contains only value types, but no reference types has a limited size. The only way to test that is at runtime using reflection.

If that is a good idea is a different question, and I'd say it's not a good idea. Serializing the raw data of a type is generally a bad idea IMO.

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262