I'm using protobuf-net (version 2.0.0.621) and having a problem serializing List type where T is my own class (it does't matter what it contains) and a surrogate is set for T.
The surrogate is set like this:
ProtoBuf.Meta.RuntimeTypeModel.Default.Add(typeof(MyClass), false).SetSurrogate(typeof(MyClassSurrogate));
MyClass:
public class MyClass
{
public int Number { get; set; }
}
[ProtoContract]
MyClassSurrogate
{
[ProtoMember(1)]
public int Number { get; set; }
}
Then I create a generic list of type MyClass instance, fill it with items and serialize it like this:
ProtoBuf.Serializer.Serialize(stream, list);
The problem occurs on deserialization, I keep getting "null" in the surrogate in the implicit operator conversion:
static public implicit operator MyClassSurrogate(MyClass myClass)
then 'myClass' is null.
If I remove the surrogate and decorate MyClass with the proto attributes, everything works fine.
Can you tell me what I'm doing wrong?
Thanks.
Adding a null check to the implicit operator conversion seems to fix the issue, i.e:
public static implicit operator MyClassSurrogate(MyClass myClass)
{
return myClass != null ? new MyClassSurrogate { Number = myClass.Number } : null;
}
The implicit operator is initially called once with a null value on deserialization with the result appearing to be ignored.
Full implementation of MyClassSurrogate:
[ProtoContract]
public class MyClassSurrogate
{
[ProtoMember(1)]
public int Number { get; set; }
public static implicit operator MyClassSurrogate(MyClass myClass)
{
return
myClass != null
? new MyClassSurrogate { Number = myClass.Number }
: null;
}
public static implicit operator MyClass(MyClassSurrogate myClass)
{
return new MyClass { Number = myClass.Number };
}
}
Full Serialization/Deserialization example:
var model = ProtoBuf.Meta.RuntimeTypeModel.Default;
model.Add(typeof(MyClassSurrogate), true);
model.Add(typeof(MyClass), false).SetSurrogate(typeof(MyClassSurrogate));
var stream = new System.IO.MemoryStream();
var list = new List<MyClass>();
for (int x = 0; x < 10; x++) list.Add(new MyClass { Number = x });
ProtoBuf.Serializer.Serialize(stream, list);
stream.Seek(0, SeekOrigin.Begin);
var xs = ProtoBuf.Serializer.Deserialize<List<MyClass>>(stream);
foreach (var x in xs) Debug.WriteLine(x.Number);
The value null is used pretty often, including during deserialization. You should be able to fix this simply by telling the conversion operator to translate null as null:
if(value == null) return null;
Thinking about it, I can probably safely add a "if both are reference types, translate null as null automatically".
Related
How Can I dynamically cast at runtime.That is I am passing a child class object in the parent class object.
public abstract class tObject
{
public tObject[] someMthode(){;}
}
public class myClass : tObject
{
public string Oth0 { get; set; }
public string Oth1 { get; set; }
public string Oth2 { get; set; }
}
I want
myClass mc=new myClass();
tObject to=mc;
myClass[] mcArray=(myClass[])mc.someMthode();//System.InvalidCastException
//Unable to cast object of type 'tObject[]' to type 'myClass[]'
but when check any element of mcArray is correct
if (mcArray[0] is myClass)
{
//return true and run this ;
}
In fact I want cast when a method return array of tObject according to the base class :
subClass[] mcArray=(subClass[])instanceOfsubClass.someMthode()
subClass or myClass and ... are unknown class , and i don't know theirs name.
Solution
public T[] Cast<T>(tObject[] mcArray ) where T : tObject
{
if (mcArray != null)
{
int cnt = mcArray.GetLength(0);
T[] t = new T[cnt];
for (int i = 0; i < cnt; i++)
{
t[i] = (T)mcArray[i];
}
return t;
}
return null;
}
Thanks all for replies.
C# does not support that kind of array conversion. C# does -- unfortunately! -- support dangerous array covariance. That is, if you had an array myClass[] then you could implicitly convert it to an array tObject[]. This means that you can do this:
Tiger[] tigers = new Tiger[10];
Animal[] animals = tigers;
animals[0] = new Turtle();
and now we have a turtle inside an array of tigers. This crashes at runtime.
That's bad enough, but you want it to go the other way -- I have an array of animals and I'd like it to be treated as an array of tigers. That does not work in C#.
As other answers have noted, you'll need to make a second array and copy the contents of the first to the second. There are a number of helper methods to do so.
Maybe?
myClass mc = new myClass();
tObject to = mc;
//myClass[] mcArray = (myClass[])mc.someMthode();//System.InvalidCastException
//Unable to cast object of type 'tObject[]' to type 'myClass[]'
var mcArray = Array.ConvertAll(mc.someMthode(), item => (myClass) item);
Well, you can call IEnumerable.Cast for that:
var myArr = mc.someMethod().Cast<MyClass>().ToArray();
As MyClass[] implements IEnumerable<MyClass>.
EDIT: What you want is quite dangerous. Look the following code:
subClass[] mcArray=(subClass[]) new BaseClass[] {...};
If this conversion would work we could now simply make the following also:
mcArray[0] = new AnotherClass();
Now you have an array of subClasses containin one item of AnotherClass also.
If you do not know the type at compile-time you cannot expect the compiler to provide any compile-time-logic for a type it doesn´t know. Thus casting to an unknown type and calling members on isn´t supported. However you may achieve this using reflection:
var runtimeType = myArr[0].GetType();
var mi = runtimeType.GetMethod("SomeMethod");
var value = mi.Invoke(myArr[0]);
This is similar to the call
var value = ((subClass)myArr[0]).SomeMethod();
Why not solve it one step up the chain and make someMethod (spelling corrected) generic:
public abstract class tObject<T> where T:tObject
{
public T[] someMethod(){;}
}
public class myClass : tObject<myClass>
{
public string Oth0 { get; set; }
public string Oth1 { get; set; }
public string Oth2 { get; set; }
}
now myClass.someMethod returns a myclass[] and that problem is solved. However, since I'm assuming that tObject does other things that just create an array of tObjects, it may cause other problems that aren't inferrable from the code you provided.
Plus it's not 100% foolproof. There's nothing stopping you (or someone else) from defining:
public class myWeirdClass : tObject<myClass>
{
}
now myWeirdClass.someMethod also returns a myClass[], and the pattern is broken. Unfortunately there's no generic constraint that requires that the generic parameter be the defining class itself, so there's no way to prevent this flaw at compile-time.
Another option may be to move the array creation outside of the class itself, since it is a code smell in itself:
public class ObjectFactory<T> where T:tObject
{
public T[] SomeMethod()
{
... create an array of Ts
}
}
I got a class in C# that has multiple overloads for different parameter types:
class Writer
{
public Writer Write(bool value)
{
// Do something with value
return this;
}
public Writer Write(double value)
{
// Do something with value
return this;
}
public Writer Write(int value)
{
// Do something with value
return this;
}
public Writer Write<T>(T value) where T : class, IInterface, new()
{
// Do something with value
return this;
}
}
class Reader
{
public Reader Read(out bool value)
{
// Retrieve value
return this;
}
public Reader Read(out double value)
{
// Retrieve value
return this;
}
public Reader Read(out int value)
{
// Retrieve value
return this;
}
public Reader Read<T>(out T value) where T : class, IInterface, new()
{
// value = new T() or null
return this;
}
}
Now I want to call Write and Read for multiple variables in a row, one of which is of an enum type. However, that enum type causes difficulties in the method resolving. (Btw: I am used to VB.NET, where Enum types are compatible to Integer parameters.)
enum MyEnum : int
{
Foo = 0, Bar = 1
}
class CallingClass
{
public void Call()
{
bool b;
double d;
int i;
IInterface o;
MyEnum e = MyEnum.Foo;
var w = new Writer();
// Unintuitive for Write
w
.Write(b)
.Write(d)
.Write(i)
.Write(o)
.Write((int) e);
// w.Write(e); // resolves to Writer.Write<T>(T)
// => Compile error: "MyEnum has to be reference type to match T"
// Even worse for Read, you need a temp variable
// and can't use fluent code anymore:
var r = new Reader();
r
.Read(out b)
.Read(out d)
.Read(out i)
.Read(out o);
int tmp;
r.Read(out tmp);
e = (MyEnum) tmp;
}
}
Is there any way I can modify Write/Read, Writer/Reader or MyEnum so that w.Write(e) will automatically resolve to Writer.Write(int) and more importantly r.Read(out e) to Reader.Read(int)?
Little late on the answer but since I was having the same issue, an overload like this should work
public void Foo(int a)
{
// do something
}
public void Foo(Enum #enum)
{
Foo(Convert.ToInt32(#enum));
}
with the where constraint:
public void Get<T>(out T value) where T : class, IInterface, new()
you are explicitly saying that T has to be a reference type (not a value type, as enums are). Try to delete class constraint.
[edit]
you can also try this, avoiding out param:
public T Get<T>() where T : new()
{
return default(T);
}
and call it as
c.Get<MyEnum>();
but again, if you add an IInterface constraint, no Enum can satisfy it.
From the comments to my question and Gian Paolo's answer, it has become clear that - opposed to VB.NET - C# does not support implicit type conversion of enum to int or vice versa, even when using tricks.
Hence, my desired "one-method handles all enum types" solution is impossible to achieve.
If you cannot (project hierarchy) or do not want to add overloads per enum type to the Writer/Reader class itself, you can create extension methods for the enum types.
1. NullReference Exception on null values inside nullable collection.
[ProtoContract]
public class ProtoTest
{
[ProtoMember(1)]
public List<string> Collecton { get; set; }
}
static void Main(string[] args)
{
ProtoTest test = new ProtoTest();
test.Collecton = new List<string>();
test.Collecton.Add("A");
test.Collecton.Add(null);
test.Collecton.Add("B");
test.Collecton.Add(null);
//This code works fine on Protobuf 1.0.0.282
//But throws exception on Protobuf 2.0.0.668
byte[] buffer = Serialize<ProtoTest>(test);
ProtoTest converted = Deserialize<ProtoTest>(buffer);
//In 1.0.0.282 converted.Collection is having 2 items excluded null values.
//In 2.0.0.668 Serialization fails with NullReference exception.
Console.Read();
}
2. Trying to Creates default instance on null values in side reference type collection
[ProtoContract]
public abstract class NullableBase
{
public NullableBase()
{
}
[ProtoMember(1)]
public int? Value { get; set; }
}
[ProtoContract]
public class NullableChild:NullableBase
{
[ProtoMember(2)]
public string StrValue { get; set; }
}
[ProtoContract]
public class ProtoTest
{
[ProtoMember(1)]
public List<NullableBase> RefCollecton { get; set; }
}
static void Main(string[] args)
{
var nullableBaseType=ProtoBuf.Meta.RuntimeTypeModel.Default.Add(typeof(NullableBase), true);
nullableBaseType.AddSubType(100, typeof(NullableChild));
ProtoTest test = new ProtoTest();
test.RefCollecton = new List<NullableBase>();
test.RefCollecton.Add(new NullableChild() { StrValue = "A" });
test.RefCollecton.Add(new NullableChild() { StrValue = "B" });
test.RefCollecton.Add(null);
byte[] buffer = Serialize<ProtoTest>(test);
//For null values on reference type Protobuf is trying to create default instance.
//Here the type is NullBase and its an abstract class. Protobuf wont be able to create it and throwing exception.
//Why Protobuf creates default instance for null values.
ProtoTest converted = Deserialize<ProtoTest>(buffer);
Console.Read();
}
We were using Protobuf 1.0.0.282 and it was excluding null values for reference types and nullable collections on serializing. But in V 2.0.0.668, its behaving in differently for nullable types and reference types . For nullable types it throws NullReferenceException on null values while serializing. But for reference types it got serialized and while deserializing its trying to create default instance for null values.
Why they removed this functionality?. Is there any specific reason for that?.
If there is any good reason, then for reference and nullable type collection it should throw nullreferenece exception right? We have tried this solution of "SupportNull" https://code.google.com/p/protobuf-net/issues/detail?id=217.
I have the following two classes. Addresses contains a list of Address. Method GetMailingAddress will scan through AddressList looking for a particular type of address.
Class Addresses
{
public List<Address> AddressList {get; set;}
public Address MailingAddress {get { return GetMailingAddress();}
}
Class Address
{
public Int? ID {get; set;}
}
To access the ID of the MailingAddress I would type the following:
Addresses obj = new Addresses();
int? I = obj.MailingAddress.ID
The problem is MailingAddress can return null. If this happens the call fails as it references ID through a null object. In this instance I would like to return null.
To work around this I use this code:
if(obj.MailingAddress == null)
{
I? = null;
}
else
{
I? = obj.MailingAddress.ID;
}
Is there a way to call obj.MailingAddress.ID and return null if MailingAddress is null without having to do the above If statement.
I could also create an additional method/property within class Addresses like this but again I see this as a work around, not a clean solution:
public int? MailingAddressID
{
if(GetMailingAddress == null)
{
return null;
}
else
{
return GetMailingAddress.ID;
}
}
First of all int is struct and you must use ? or Nullable<int> for making it nullable and then:
int? myInt = obj.MailingAddress == null ? (int?)null : (int?)obj.MailingAddress.Id;
But, in C# 6 you can use ? operator which is sometimes called Safe Navigation Operator :
int? myInt = obj?.MailingAddress?.Id;
As an additional note, you can use Null Object Pattern. You can learn it from here and use this pattern also. The use of Null Object pattern simplifies the code and makes it less error prone.
Here is a silly implementation of C# 6 Null Propagation syntax in C# 5:
using System;
using System.Diagnostics;
public class Program
{
public static void Main()
{
var foo = new Foo { Bar = new Bar { Baz = "Hello" } };
var foo1 = new Foo();
var i = foo._(_=>_.Bar)._(_=>_.Baz); //equivalent to foo?.Bar?.Baz in C# 6
Console.WriteLine("i is '{0}'", i); //should be 'Hello'
var j = foo1._(_=>_.Bar)._(_=>_.Baz); //equivalent to foo1?.Bar?.Baz in C# 6
Console.WriteLine("j is '{0}'",j); //should be '' since j is null, but shouldn't throw exception either.
Console.WriteLine("js is null? {0}", j == null);
}
}
public class Foo
{
public Bar Bar { get; set; }
}
public class Bar
{
public string Baz { get; set; }
}
public static class ObjectExtension
{
//Probably not a good idea to name your method _, but it's the shortest one I can find, I wish it could be _?, but can't :(
public static K _<T, K>(this T o, Func<T, K> f)
{
try
{
var z = f(o);
return z;
}
catch(NullReferenceException nex)
{
Trace.TraceError(nex.ToString());
return default(K);
}
}
}
Basically I want to do foo?.Bar?.Baz, but since the syntax is not supported, extension method, Func<..> and generic to the rescue...
This way you don't need to change your object to nullable version, but you need to specify their type in the call to extension method _. foo._(_=>_.Bar)._(_=>_.Baz) looks a bit weird, but quite terse :)
Live sample at: https://dotnetfiddle.net/9R8bku
So I have this class:
public class Foo<T> where T : ???
{
private T item;
public bool IsNull()
{
return item == null;
}
}
Now I am looking for a type constraint that allows me to use everything as type parameter that can be null. That means all reference types, as well as all the Nullable (T?) types:
Foo<String> ... = ...
Foo<int?> ... = ...
should be possible.
Using class as the type constraint only allows me to use the reference types.
Additional Information:
I am writing a pipes and filters application, and want to use a null reference as the last item that passes into the pipeline, so that every filter can shut down nicely, do cleanup, etc...
If you are willing to make a runtime check in Foo's constructor rather than having a compile-time check, you can check if the type is not a reference or nullable type, and throw an exception if that's the case.
I realise that only having a runtime check may be unacceptable, but just in case:
public class Foo<T>
{
private T item;
public Foo()
{
var type = typeof(T);
if (Nullable.GetUnderlyingType(type) != null)
return;
if (type.IsClass)
return;
throw new InvalidOperationException("Type is not nullable or reference type.");
}
public bool IsNull()
{
return item == null;
}
}
Then the following code compiles, but the last one (foo3) throws an exception in the constructor:
var foo1 = new Foo<int?>();
Console.WriteLine(foo1.IsNull());
var foo2 = new Foo<string>();
Console.WriteLine(foo2.IsNull());
var foo3= new Foo<int>(); // THROWS
Console.WriteLine(foo3.IsNull());
I don't know how to implement equivalent to OR in generics. However I can propose to use default key word in order to create null for nullable types and 0 value for structures:
public class Foo<T>
{
private T item;
public bool IsNullOrDefault()
{
return Equals(item, default(T));
}
}
You could also implement you version of Nullable:
class MyNullable<T> where T : struct
{
public T Value { get; set; }
public static implicit operator T(MyNullable<T> value)
{
return value != null ? value.Value : default(T);
}
public static implicit operator MyNullable<T>(T value)
{
return new MyNullable<T> { Value = value };
}
}
class Foo<T> where T : class
{
public T Item { get; set; }
public bool IsNull()
{
return Item == null;
}
}
Example:
class Program
{
static void Main(string[] args)
{
Console.WriteLine(new Foo<MyNullable<int>>().IsNull()); // true
Console.WriteLine(new Foo<MyNullable<int>> {Item = 3}.IsNull()); // false
Console.WriteLine(new Foo<object>().IsNull()); // true
Console.WriteLine(new Foo<object> {Item = new object()}.IsNull()); // false
var foo5 = new Foo<MyNullable<int>>();
int integer = foo5.Item;
Console.WriteLine(integer); // 0
var foo6 = new Foo<MyNullable<double>>();
double real = foo6.Item;
Console.WriteLine(real); // 0
var foo7 = new Foo<MyNullable<double>>();
foo7.Item = null;
Console.WriteLine(foo7.Item); // 0
Console.WriteLine(foo7.IsNull()); // true
foo7.Item = 3.5;
Console.WriteLine(foo7.Item); // 3.5
Console.WriteLine(foo7.IsNull()); // false
// var foo5 = new Foo<int>(); // Not compile
}
}
I ran into this issue for a simpler case of wanting a generic static method that could take anything "nullable" (either reference types or Nullables), which brought me to this question with no satisfactory solution. So I came up with my own solution which was relatively easier to solve than the OP's stated question by simply having two overloaded methods, one that takes a T and has the constraint where T : class and another that takes a T? and has where T : struct .
I then realized, that solution can also be applied to this problem to create a solution that is checkable at compile time by making the constructor private (or protected) and using a static factory method:
//this class is to avoid having to supply generic type arguments
//to the static factory call (see CA1000)
public static class Foo
{
public static Foo<TFoo> Create<TFoo>(TFoo value)
where TFoo : class
{
return Foo<TFoo>.Create(value);
}
public static Foo<TFoo?> Create<TFoo>(TFoo? value)
where TFoo : struct
{
return Foo<TFoo?>.Create(value);
}
}
public class Foo<T>
{
private T item;
private Foo(T value)
{
item = value;
}
public bool IsNull()
{
return item == null;
}
internal static Foo<TFoo> Create<TFoo>(TFoo value)
where TFoo : class
{
return new Foo<TFoo>(value);
}
internal static Foo<TFoo?> Create<TFoo>(TFoo? value)
where TFoo : struct
{
return new Foo<TFoo?>(value);
}
}
Now we can use it like this:
var foo1 = new Foo<int>(1); //does not compile
var foo2 = Foo.Create(2); //does not compile
var foo3 = Foo.Create(""); //compiles
var foo4 = Foo.Create(new object()); //compiles
var foo5 = Foo.Create((int?)5); //compiles
If you want a parameterless constructor, you won't get the nicety of overloading, but you can still do something like this:
public static class Foo
{
public static Foo<TFoo> Create<TFoo>()
where TFoo : class
{
return Foo<TFoo>.Create<TFoo>();
}
public static Foo<TFoo?> CreateNullable<TFoo>()
where TFoo : struct
{
return Foo<TFoo?>.CreateNullable<TFoo>();
}
}
public class Foo<T>
{
private T item;
private Foo()
{
}
public bool IsNull()
{
return item == null;
}
internal static Foo<TFoo> Create<TFoo>()
where TFoo : class
{
return new Foo<TFoo>();
}
internal static Foo<TFoo?> CreateNullable<TFoo>()
where TFoo : struct
{
return new Foo<TFoo?>();
}
}
And use it like this:
var foo1 = new Foo<int>(); //does not compile
var foo2 = Foo.Create<int>(); //does not compile
var foo3 = Foo.Create<string>(); //compiles
var foo4 = Foo.Create<object>(); //compiles
var foo5 = Foo.CreateNullable<int>(); //compiles
There are few disadvantages to this solution, one is that you may prefer using 'new' to construct objects. Another is that you won't be able to use Foo<T> as a generic type argument for a type constraint of something like: where TFoo: new(). Finally is the bit of extra code you need here which would increase especially if you need multiple overloaded constructors.
As mentioned, you cannot have a compile-time check for it. Generic constraints in .NET are severely lacking, and do not support most scenarios.
However I consider this to be a better solution for run-time checking. It can be optimized at JIT compilation time, since they're both constants.
public class SomeClass<T>
{
public SomeClass()
{
// JIT-compile time check, so it doesn't even have to evaluate.
if (default(T) != null)
throw new InvalidOperationException("SomeClass<T> requires T to be a nullable type.");
T variable;
// This still won't compile
// variable = null;
// but because you know it's a nullable type, this works just fine
variable = default(T);
}
}
Such a type constraint is not possible. According to the documentation of type constraints there is not constraint that captures both the nullable and the reference types. Since constraints can only be combined in a conjunction, there is no way to create such a constraint by combination.
You can, however, for your needs fall back to an unconstraint type parameter, since you can always check for == null. If the type is a value type the check will just always evaluate to false. Then you'll possibly get the R# warning "Possible compare of value type with null", which is not critical, as long as the semantics is right for you.
An alternative could be to use
object.Equals(value, default(T))
instead of the null check, since default(T) where T : class is always null. This, however, means that you cannot distinguish weather a non-nullable value has never been set explicitly or was just set to its default value.
I use
public class Foo<T> where T: struct
{
private T? item;
}
If you only want to allow nullable value types and reference types, and disallow non-nullable value types, then I think you're out of luck as of C# 9.
I am writing a pipes and filters application, and want to use a null reference as the last item that passes into the pipeline, so that every filter can shut down nicely, do cleanup, etc...
In other words, you need to reserve a special value that indicates the end-of-stream.
Consider creating a wrapper type that provides this. It'd be similar to how Nullable<T> is implemented, and has the additional benefit of allowing a non-end-of-stream null value to be transmitted, should that be useful.
public readonly struct StreamValue<T>
{
public bool IsEndOfStream { get; }
public T Value { get; }
}
public class Foo<T>
{
private T item;
public Foo(T item)
{
this.item = item;
}
public bool IsNull()
{
return object.Equals(item, null);
}
}
var fooStruct = new Foo<int?>(3);
var b = fooStruct.IsNull();
var fooStruct1 = new Foo<int>(3);
b = fooStruct1.IsNull();
var fooStruct2 = new Foo<int?>(null);
b = fooStruct2.IsNull();
var fooStruct3 = new Foo<string>("qqq");
b = fooStruct3.IsNull();
var fooStruct4 = new Foo<string>(null);
b = fooStruct4.IsNull();