|
static void function(ref T[] i)
Your code declares i as a T. In order to access it as an array, you need to specify it as one (unless you like pointer arithmetic and a whole world of pain). But your function code is concerning. The idea of generics is to make something type-safe. What happens if T is a String? A nasty error. Incidentally, you should have gotten another error at the invocation point (something like "Cannot implicitly convert between int[] and int")
|
|
|
|
|
You have to declare the argument as an array if it is one. Like so:
static void function(ref T[] i)
But your next line:
int a = i[0];
won't compile anyway, since the compiler cannot garantuee that T is of a type that is convertible to an int .
Use something like this instead:
static void function(ref T[] i) where T : struct
{
try
{
int a = Convert.ToInt(i[0]);
}
catch((FormatException)
{
}
...
Regards
Thomas
www.thomas-weller.de
Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning. Programmer - an organism that turns coffee into software.
|
|
|
|
|
Thanks Thomas, I edit the question and explained it better. My problem is basically to access the "i" value when the function receive single types and arrays too, my problem is to get the value of each element when the type is an array (which I can check using i.GetType().IsArray).
Thanks anyway.
|
|
|
|
|
Then there's a small problem with my code. Try this:
public static IEnumerable<t> GetIEnumerable<t>(T input)
{
if(input is IEnumerable<t>)
{
foreach(T element in (input as IEnumerable<t>))
yield return element;
}
else
yield return input;
}</t></t></t></t>
As a bonus, this also deals with all IEnumerables (ArrayLists, List<t>s, etc), not just arrays. You could replace IEnumerable<t> with T[] and get your original query.
|
|
|
|
|
It doesn't work: Unable to cast object of type 'System.Int32' to type 'System.Int32[]'.
|
|
|
|
|
In this case you can simply declare two overloads, one for normal elements and one for arrays:
static void function(ref T i)
{
DoSomething(i);
}
static void function(ref T[] i)
{
foreach(T element in i)
{
DoSomething(element);
}
}
static void DoSomething(ref T i)
{
...
}
Regards
Thomas
www.thomas-weller.de
Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning. Programmer - an organism that turns coffee into software.
|
|
|
|
|
Thomas Weller wrote:
catch(FormatException)
FTFY (extra bracket)
|
|
|
|
|
I was wondering if somehow it is possible to make objects readonly if referenced by another assembly but writeable when accessed internally?
For example I have a scenario where I need to pass objects to UI. UI must not be allowed to temper with the object in any form or fashion but the business layer should have full access to the object as we need to do some computation after the object is inialized by the DAL.
I was just wondering if there is a preferred way of dealing with situations like these that I am not aware of?
Would appreciate the help ...
Thanks in advance.
|
|
|
|
|
Like so?
private int p;
public int Property
{
internal set { p = value; }
get { return p; }
}
warning: untested
|
|
|
|
|
student_rhr wrote: I was just wondering if there is a preferred way of dealing with situations like these
There are three ways (that I know of... ):
1.
Create an interface that only declares the elements (e.g. property getters) that the UI should see. 'Implement' it on the class of interest (actually you only have to declare it). Then pass this interface around instead of the 'real' object.
2.
Implement the Data Transfer Object design pattern to handle the situation. It is described here^. In
short, this method declares a struct or immutable class with all the data of interest, and if you have to pass around
these data you create such an object (with a copy of the relevant data) for this purpose.
3.
Declare the objects property setters and methods (if they are able to change the objects state) as internal, everything else as public. 'Internal' means exactly that: Public for everything inside the same assembly, invisible for everything outside.
What best suits your needs depends on your overall architecture and the situation...
Hope this helps.
Regards
Thomas
www.thomas-weller.de
Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning. Programmer - an organism that turns coffee into software.
|
|
|
|
|
Something like automatic properties? (Not available in .Net framework versions below 3.0)
public MyType Property { get; internal set; }
|
|
|
|
|
I have a class that is serializable (using the SerializableAttribute). I have also implemented the ISerializable to that class. I am able to serialize/deserialize the object by doing the following:
string xml = string.Empty;
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings();
StringWriter sw = new StringWriter();
settings.OmitXmlDeclaration = true;
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(sw, settings))
{
XmlSerializer ser = new XmlSerializer(typeof(Content));
ser.Serialize(writer, this, ns);
return sw.ToString();
}
My problem is when I try to bind the object to a ViewState, I get the following error:
Type 'System.Xml.XmlNode' in Assembly 'System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable
Below are my classes (shortened). Any help is appreciated. Thanks in advance.
Content Class:
[Serializable]
[DataObject(true)]
public class Content : ISerializable
{
public Content() { }
public Content(SerializationInfo info, StreamingContext context)
{
this.contentCollection = (List<Content> )info.GetValue("ContentCollection", typeof(List<Content> ));
this.ContentId = info.GetInt64("ContentId");
this.Name = info.GetString("Name");
this.Owner = (Owner)info.GetValue("Owner", typeof(Owner));
}
private List<Content> contentCollection;
[XmlArray("ContentCollection")]
public List<content> ContentCollection
{
get
{
if (contentCollection == null) contentCollection = new List<content>();
return this.contentCollection;
}
}
private System.Int64 contentIdField;
[XmlAttribute("ContentId")]
public System.Int64 ContentId
{
get { return this.contentIdField; }
set { this.contentIdField = value; }
}
private System.String nameField;
[XmlElement("Name")]
public System.String Name
{
get { return this.nameField; }
set { this.nameField = value; }
}
private Owner owner;
[XmlElement("Owner")]
public Owner Owner
{
get { return this.owner; }
set { this.owner = value; }
}
#region ISerializable Members
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("ContentCollection", this.ContentCollection);
info.AddValue("ContentId", this.ContentId);
info.AddValue("Name", this.Name);
info.AddValue("Owner", this.Owner);
}
#endregion</content></content>
Owner Class:
[Serializable]
[DataObject(true)]
public class Owner : ISerializable
{
public Owner() { }
public Owner(SerializationInfo info, StreamingContext context)
{
this.OwnerId = info.GetInt64("OwnerId");
}
private long ownerId;
[Browsable(false)]
[XmlAttribute("OwnerId")]
public long OwnerId
{
get { return ownerId; }
set { ownerId = value; }
}
#region ISerializable Members
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("OwnerId", this.ownerId);
}
#endregion
}
|
|
|
|
|
Turns out ViewStates does not support Xml Objec serialization. Instead it uses the LosFormatter so BinaryFormatter should work (havent tried yet).
However, Session states do support Xml serialization.
Suggestions/comments still welcome.
|
|
|
|
|
I tend to use binary serialization for several reasons:
1) Size. Binary < XML < Soap
If you have a lot of data, the difference can be "significant" and result in quicker load times. For example, Bin: 1.4Mb, XML: 2.5Mb, Soap: 9.4Mb
2) The XmlSerializer type will only serialize public data fields or private data exposed by public properties. Private data not exposed from properties will be ignored.
This is way too easy to forget, and can cause some very odd problems later.
|
|
|
|
|
Thanks for your reply.
Currently I am receiving an Xml which I an deserializing into a custom class. This custom class contains the [Serializable] attribute and also implements the ISerializable interface (probably extra work i did not need to do). The properties of this class contains the [XmlElement] and [XmlAttribute] attributes. Does this mean that this class can only be serialized/deserialized using the XmlSerializer only?
When I attempt to serialize/deserialize using the BinaryFormatter, I get the following error:
Type 'System.Xml.XmlNode' in Assembly 'System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.
I also get this error when trying to set the ViewState item value to the object.
I get the feeling that the binarySerializer is trying to serialize an object that is already xmlserialized...
Is it possible for me to use mutlitple types of serializers on a single object?
|
|
|
|
|
If you are receiving an XML serialization, then the only thing you can deserialize it with is an XmlSerializer - it is entirly possible that the error you are getting is a reflection of this. I.e. that the XmlNode entries are private, not available as public properties and thus the tree can be saved by a XmlSerializer, but not with a BinaryFormatter since this will try to save all private variables as well. Since XmlNore does not appear to have a [Serializable]attribute, I think you are stuck with XmlSerializer.
You could use multiple type of serializer, but since each would contain the same data this would just increase the effort, without producing a benefit.
|
|
|
|
|
So we all know that exceptions for anything other than exceptional circumstances are a bad thing. Using them to control execution flow is criminal.
For fun, in a quick console app I created a loop that just created and caught exceptions. Anyone care to guess how many exceptions you can throw a second? (Typical development PC)
Regards,
Rob Philpott.
|
|
|
|
|
I'm guessing >100, <1000
I are troll
|
|
|
|
|
That's a good guess! But as Luc points out below, I haven't really done this correctly. Within Visual Studio in debug, I can throw 370 a second before the process dries out so about 2-3ms per exception.
Outside the VS debugger, its much, much faster. 1000 exceptions take 17ms to run, so all in all, its nowhere near as bad as I thought.
Regards,
Rob Philpott.
|
|
|
|
|
Rob Philpott wrote: its much, much faster. 1000 exceptions take 17ms to run
I didn't imagine them being that fast! I thought that the average time would be near the 10 ms for a single exception.
with 1000's in <20 one can use them in a loop
--edit--
Shocked enough to be having trouble with typing
I are troll
|
|
|
|
|
Sorry to bother you again, but I am always suspicious when someone has measured a time span of 16 or 17 msec, since that is pretty much what a system tick takes on most popular hardware/software combinations. Have you been using StopWatch or PerformanceCounters, or did you just look at DateTime.Now?
I suggest you use StopWatch, or run a loop 100 times as long; and you may want and learn more about timing issues by reading my timers article...
|
|
|
|
|
Fair point - I've been using my new friend Stopwatch, which on this hardware at least is a great deal more accurate than DateTime.Now.
Just did 10,000 - took 178ms.
Regards,
Rob Philpott.
|
|
|
|
|
That's OK then.
Now to see how slow that really is, you should replace the exception by a somewhat equivalent return or goto statement and see the difference.
|
|
|
|
|
is that a debug build running inside Visual Studio? (which VS?)
is the first exception included in the measurement?
Visual used to be very slow at dealing with the first exception; and for throughput measurements one should not include the beginning (unless it gets averaged out by observing a large time, say > 1 minute).
could be less than 1.
|
|
|
|
|
Good points - I'll check the results outside VS.
Regards,
Rob Philpott.
|
|
|
|