473,545 Members | 4,241 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Constraining a generic method to struct and string

Hi!

While implementing a property manager (that supports key / value pairs), I
was wondering how to constrain T to a struct or string type. Basically, I
guess what I'm looking for is the common denominator for structs and strings
and while looking through the SDK I only noticed the IEquatable<T>
interface.

So I implemented the class with methods such as the following, but I'm aware
that this is not the right approach.

// Initial implementation
public void Add<T>(string key, T value) where T : IEquatable<T>
{
this.AddPropert y(key, value);
}

// Proposed implementation
public void Add<T>(string key, T value) where T : IEquatable<T>
{
if (! (value is ValueType) || ! (value is string)) { throw new
InvalidOperatio nException("mes sage"); }

this.AddPropert y(key, value);
}

--
With regards
Anders Borum / SphereWorks
Microsoft Certified Professional (.NET MCP)

Jun 27 '08 #1
5 4589
Anders Borum wrote:
While implementing a property manager (that supports key / value pairs),
I was wondering how to constrain T to a struct or string type.
Though it's not the same as implementing a single method, you can do it with
overloads:

public void Foo<T>(T value) where T : struct { ... }
public void Foo(string value) { ... }

However, I would be very surprised if you actually needed such a construct,
so it's worth taking a closer look.
Basically, I guess what I'm looking for is the common denominator for
structs and strings and while looking through the SDK I only noticed the
IEquatable<Tint erface.
There is no common denominator for structs and strings, other than Object,
and it's unclear what exactly you're after. In what circumstances would it
be meaningful to restrict types to structs or strings? Keep in mind that a
struct is really just a sealed class with value type semantics, while a
string is an immutable reference type. They're not at all comparable.

What exactly do you require of keys that makes you think you need to
restrict them to strings and structs?
So I implemented the class with methods such as the following, but I'm
aware that this is not the right approach.

// Initial implementation
public void Add<T>(string key, T value) where T : IEquatable<T>
{
this.AddPropert y(key, value);
}

// Proposed implementation
public void Add<T>(string key, T value) where T : IEquatable<T>
{
if (! (value is ValueType) || ! (value is string)) { throw new
InvalidOperatio nException("mes sage"); }
What's "message"? :-)
this.AddPropert y(key, value);
}
Again, what are you trying to do here? Why do you think you need to use
value types and strings? If you want the ability to copy an object,
constrain the type to ICloneable and use .Clone(). If you need to compare
them for equality, then IEquatable<is indeed a good choice. It seems like
you're imposing an arbitrary restriction that doesn't gain you anything.

--
J.
http://symbolsprose.blogspot.com
Jun 27 '08 #2
On Mon, 14 Apr 2008 13:48:20 -0700, Anders Borum <an****@spherew orks.dk>
wrote:
Hi!

While implementing a property manager (that supports key / value pairs),
I was wondering how to constrain T to a struct or string type.
Basically, I guess what I'm looking for is the common denominator for
structs and strings and while looking through the SDK I only noticed the
IEquatable<Tint erface.

So I implemented the class with methods such as the following, but I'm
aware that this is not the right approach.
It seems to me that your proposed implementation, in which you check the
actual type, is about as good as you're going to get. Except that I
wouldn't bother with the constraint.

I don't think structs are provided a default IEquatable<Tint erface so
not all structs would necessarily have that interface anyway. And even if
they did, there's nothing about your description that suggests that you
really care about the members of the IEquatable<Tint erface anyway. So
the constraint doesn't really represent what you're trying to do, and
would in fact be misleading to anyone trying to figure out the method's
declaration.

Pete
Jun 27 '08 #3
>*And even if *
they did, there's nothing about your description that suggests that you *
really care about the members of the IEquatable<Tint erface anyway.
Absolutely; but I know where you're coming from - most times people
ask about "struct and strings" it is to detect changes in values (for
things such as INotifyProperty Changed). Actually, in many cases I've
found that the IEquatable<Tmet hod just gets in the way - especially
if generics are involved (constraints accumulate, which can mean you
have piles of constraints). I generally use
EqualityCompare r<T>.Default instead of an explicit IEquatable<T>
constraint - this works the same (slightly different IL of course),
but doesn't need the constraint, and also works (via Equals) for
legacy types that don't implement IEquatable<T>.

Marc
Jun 27 '08 #4
Regardless, for unknown types I'd still require the class / struct to
provide a Parse(string) method that can be called via reflection when
deserializing the values.
Can I recommend XmlConvert, i.e.

XmlConvert.To[...] (deserialize), or XmlConvert.ToSt ring (serialize)

This will use suitable xml formats, and (IIRC) invariant culture.
As a secondary to XmlConvert, TypeDescriptor is probably a next best
thing - i.e.

TypeDescriptor. GetConverter(ty peof(T)).Conver t[To|From]InvariantString

Also - watch for a typo (Int63) - that would break things pretty
quickly...

Of course, another approach would be to use XmlSerializer or
DataContractSer ializer, which will cope with more scenarios than I
care to have to list.

Marc
Jun 27 '08 #5
Hi Marc

Sorry for the delay (I was busy writing APIs). Thanks for pointing out the
typo!

I decided to go with the XmlConvert because of the locale independence as I
couldn't find any reason to reproduce the implementation in that class just
to save a few method calls. I would have liked a generic
XmlConvert.ToSt ring(object) signature, but I guess the implementation I came
up with is quite good in terms of maintenance and performance (the latter is
great).
Of course, another approach would be to use XmlSerializer or
DataContractSer ializer, which will cope with more scenarios than I
care to have to list.
Again, the PropertyManager was intended as a storage for generic
configuration values / list of values. Not entire serialized graphs
(although it's definately supported by means of using a string configuration
value).

Here's the "CmsXmlConverte r" class I ended up implementing - it may be of
use to others. As can be read from above, I'd have liked an
XmlConvert.ToSt ring(object) method, but decided to skip the reflection
(emit) approch and wrote a switched implementation instead (which works very
well, I might add).

If you've got additional comments, I'm always very interested - and thanks
for the information so far!

public static string GetString(strin g typeName, object value)
{
if (value == null) { return null; }

switch (typeName)
{
case "System.String" : { return (string) value; }
case "System.Gui d": { return XmlConvert.ToSt ring((Guid) value); }
case "System.DateTim e": { return XmlConvert.ToSt ring((DateTime) value,
XmlDateTimeSeri alizationMode.U tc); }
case "System.DateTim eOffset": { return
XmlConvert.ToSt ring((DateTimeO ffset) value); }
case "System.TimeSpa n": { return XmlConvert.ToSt ring((TimeSpan)
value); }
case "System.Boo l": { return XmlConvert.ToSt ring((bool) value); }
case "System.Byt e": { return XmlConvert.ToSt ring((byte) value); }
case "System.Cha r": { return XmlConvert.ToSt ring((char) value); }
case "System.Decimal ": { return XmlConvert.ToSt ring((decimal) value); }
case "System.Double" : { return XmlConvert.ToSt ring((double) value); }
case "System.Single" : { return XmlConvert.ToSt ring((float) value); }
case "System.Int 16": { return XmlConvert.ToSt ring((short) value); }
case "System.Int 32": { return XmlConvert.ToSt ring((int) value); }
case "System.Int 64": { return XmlConvert.ToSt ring((long) value); }
case "System.SBy te": { return XmlConvert.ToSt ring((sbyte) value); }
case "System.UInt16" : { return XmlConvert.ToSt ring((ushort) value); }
case "System.UInt32" : { return XmlConvert.ToSt ring((uint) value); }
case "System.UInt64" : { return XmlConvert.ToSt ring((ulong) value); }
default: { return value.ToString( ); }
}
}

public static object GetObject(strin g typeName, string value)
{
if (string.IsNullO rEmpty(value)) { return null; }

return GetParser(typeN ame)(value);
}

public static Func<string, objectGetParser (Type type)
{
return GetParser(type. FullName);
}

public static Func<string, objectGetParser (string typeName)
{
switch (typeName)
{
case "System.String" : { return (p) =p; }
case "System.Gui d": { return (p) =XmlConvert.ToG uid(p); }
case "System.DateTim e": { return (p) =XmlConvert.ToD ateTime(p,
XmlDateTimeSeri alizationMode.U tc); }
case "System.DateTim eOffset": { return (p) =>
XmlConvert.ToDa teTimeOffset(p) ; }
case "System.TimeSpa n": { return (p) =XmlConvert.ToT imeSpan(p); }
case "System.Boo l": { return (p) =XmlConvert.ToB oolean(p); }
case "System.Byt e": { return (p) =XmlConvert.ToB yte(p); }
case "System.Cha r": { return (p) =XmlConvert.ToC har(p); }
case "System.Decimal ": { return (p) =XmlConvert.ToD ecimal(p); }
case "System.Double" : { return (p) =XmlConvert.ToD ouble(p); }
case "System.Single" : { return (p) =XmlConvert.ToS ingle(p); }
case "System.Int 16": { return (p) =XmlConvert.ToI nt16(p); }
case "System.Int 32": { return (p) =XmlConvert.ToI nt32(p); }
case "System.Int 64": { return (p) =XmlConvert.ToI nt64(p); }
case "System.SBy te": { return (p) =XmlConvert.ToS Byte(p); }
case "System.UInt16" : { return (p) =XmlConvert.ToU Int16(p); }
case "System.UInt32" : { return (p) =XmlConvert.ToU Int32(p); }
case "System.UInt64" : { return (p) =Convert.ToUInt 64(p); }
default:
{
Type type = Type.GetType(ty peName);
MethodInfo info = type.GetMethod( "Parse", new Type[] {
typeof(string) });

if (info == null) { throw new
InvalidOperatio nException(stri ng.Format("Unab le to find the Parse(string
value) method for type: {0}.", type.FullName)) ; }

return (p) =info.Invoke(nu ll, new object[] { p });
}
}
}

--
With regards
Anders Borum / SphereWorks
Microsoft Certified Professional (.NET MCP)

Jun 27 '08 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

17
3295
by: Andreas Huber | last post by:
What follows is a discussion of my experience with .NET generics & the ..NET framework (as implemented in the Visual Studio 2005 Beta 1), which leads to questions as to why certain things are the way they are. ***** Summary & Questions ***** In a nutshell, the current .NET generics & .NET framework make it sometimes difficult or even...
4
2038
by: Jethro Guo | last post by:
C++ template use constraint by signature,It's very flexible to programmer but complex for complier, and at most time programmer can not get clear error message from complier if error occur. C# generic use constraint by type,complier is relaxed, but it is very limited to programmer.Is there a way to get merits of both? Maybe the following...
8
1821
by: JAL | last post by:
Here is my first attempt at a deterministic collection using Generics, apologies for C#. I will try to convert to C++/cli. using System; using System.Collections.Generic; using System.Text; namespace DeterminedGenericCollection { // I got tired of copy and pasting IDisposable
3
3539
by: markww | last post by:
Hi, I have a wrapper around some 3rd party database library function. The pseudo code looks like the following - it is meant to open a table in a database, extract values from a table, then copy it into my own user defined structures. Since the process of opening and retrieving data from the database is exactly the same for all struct...
3
14989
by: BombDrop | last post by:
Can any one help I have a method that will return a List to be bound as a datasource to a combobox see code for population below. I get the following error when i try to compile Error 29 Cannot implicitly convert type 'System.Collections.Generic.List<Prsym.ComboPopulation.ComboInfo>' to 'System.Collections.Generic.List<T> '
4
7825
by: =?Utf-8?B?RXRoYW4gU3RyYXVzcw==?= | last post by:
Hi, I have written a generic method which does different things depending on the type of the parameter. I got it to work, but it seems really inelegant. Is there a better way to do this? In the code below, ColumnMap is a simple struct which basically has three properties, Header (a string), Index (an int), TypeOfData (which is a DataType...
26
3595
by: raylopez99 | last post by:
Here is a good example that shows generic delegate types. Read this through and you'll have an excellent understanding of how to use these types. You might say that the combination of the generic delegate type expression in just the right place and a well-named method means we can almost read the code out loud and understand it without even...
3
2248
by: Anders Borum | last post by:
Hi I need to invoke a generic method determined at runtime. The method has two arguments, a string and a generic type that is constrained to a struct: public void Add<T>(string key, T value) where T : struct The method is an instance member located on a class called CmsPropertyManager. I also have a number of other "Add" methods with...
0
2336
by: =?Utf-8?B?TW9ydGVuIFdlbm5ldmlrIFtDIyBNVlBd?= | last post by:
"Anders Borum" wrote: Hi Anders, I'm afraid the GetMethod() does not currently support filtering on generic parameters so you will have to loop through the existing methods using GetMethods() MethodInfo methods = t.GetMethods();
0
7464
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7396
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
7656
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
7805
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7413
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
4943
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3440
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
1012
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
700
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.