I know it sounds stupid but I am just being curious. My lecturer asked this question and we were clueless. :D
-
1Because it is counterintuitive. Serializable implies a 'MarshalByValueObject', and not a remote reference for what `MarshalByRefObject` is used. It would probably confuse the hell out of the remoting system ;p (btw, not a stupid question) – leppie Apr 23 '14 at 09:10
-
@Sergey I already saw that question but that was for two different classes. What I meant was for a single class. There is a similar question posted here [link](http://stackoverflow.com/questions/8799202/what-happens-when-an-object-derives-from-marshalbyrefobject-and-is-also-marked?rq=1) but that answer is confusing. – Gayan Jayasingha Apr 23 '14 at 09:15
-
@leppie no, I disagree; I don't think it implies that at all – Marc Gravell Apr 23 '14 at 09:34
-
1Your lecturer is wrong. – Marc Gravell Apr 23 '14 at 09:36
2 Answers
Your lecturer is incorrect.
foreach(var type in typeof(Uri).Assembly.GetTypes())
{
if (type.IsAbstract) continue;
if (!Attribute.IsDefined(type, typeof(SerializableAttribute))) continue;
if (!typeof(MarshalByRefObject).IsAssignableFrom(type)) continue;
Console.WriteLine(type.FullName);
}
shows (and note that I'm only looking at a single assembly here):
System.Media.SoundPlayer
System.Net.FileWebRequest
System.Net.FileWebResponse
System.Net.HttpWebRequest
System.Net.HttpWebResponse
System.Diagnostics.EventLogEntry
and sure enough, http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.aspx shows:
[SerializableAttribute]
public class HttpWebRequest : WebRequest,
ISerializable
noting also:
[SerializableAttribute]
public abstract class WebRequest : MarshalByRefObject,
ISerializable
For mscorlib (typeof(object)
), we get:
System.IO.Stream+SyncStream
System.IO.DirectoryInfo
System.IO.FileInfo
System.IO.MemoryStream
System.IO.TextReader+SyncTextReader
System.IO.StreamReader
System.IO.TextWriter+SyncTextWriter
System.IO.StreamWriter
System.IO.StringReader
System.IO.StringWriter
System.IO.Stream+NullStream
System.IO.TextReader+NullTextReader
System.IO.TextWriter+NullTextWriter
That's enough concrete counter-examples, I suspect.
I suspect that your lecturer is only thinking of remoting, i.e. where we expect something to either be remoted as a proxy/stub pair, or by serialization. However, this is invalid.
[Serializable]
is also used purely for serialization purposes outside of remoting- remotable classes can be (and usually are) used separately-to and independently-of remoting
- remoting is dead; tell them to stop teaching remoting, please
Or alternatively, consider:
When remoting is used, MarshalByRefObject
indicates that the object should be remoted by proxy/stub - otherwise, the object needs to be serializable, so [Serializable]
is required. However, the reverse is not true: [Serializable]
does not mean "marshal by value" (simply: the lack of MarshalByRefObject
is what means "marshal by value"). A type can be both serializable and remoted by proxy/stub. There is no conflict here.

- 1,026,079
- 266
- 2,566
- 2,900
-
If remoting is dead, then how do you do cross appdomain object references? Ups, it is not - remoting is still used extremely widely in standard scenarios like this (and there are a great many uses to put stuff in appdomains, to be able to totally unload it). – TomTom Apr 23 '14 at 09:39
-
A small follow-up q. Say, I have a `List` of MBR object, which I serialize as XML and then de-serialize inside a different domain. I expect I'd get a copy of the list which contains proxies to the original MBR objects, all OK. However, what if I restart the app (the MBR objects are gone), the de-serialize the XML graph? Am I gonna get a runtime error, or copies of the original MBR objects? – noseratio Apr 23 '14 at 09:42
-
-
@TomTom yes, I will grant you that: remoting is still viable in AppDoman scenarios (although other approaches will work too). I shudder when people are using remoting as a inter-process / inter-machine communication device, though – Marc Gravell Apr 23 '14 at 09:46
-
@leppie because not everyone knows that `[Serializable]` has special handling (the compiler doesn't even add the `SerializableAttribute`, really), and I wanted it to be as obvious as possible. But yes, `.IsSerializable` is much more efficient here (no attribute spoofing required) – Marc Gravell Apr 23 '14 at 09:47
-
-
-
@Noseratio why would you expect proxies to the original MBR records? Since you are serializing to XML, I would not expect that *at all*. – Marc Gravell Apr 23 '14 at 09:48
-
@MarcGravell: It is much harder to blow your leg off with WCF though. :) – leppie Apr 23 '14 at 09:49
-
1@leppie only because the `ILegBlowOffChannelProxyFactory` is poorly documented, and can only be accessed at a silly point in the WCF pipe. – Marc Gravell Apr 23 '14 at 09:50
-
@Noseratio: You can use serialization surrogates for that (I do the same in IronScheme, to intern symbols and boolean values on deserialization). – leppie Apr 23 '14 at 09:50
-
@MarcGravell, I never tried that, but I expect there has to be a way to persist a reference to an MBR object as a unique string, for transferring it over the wire. In DCOM, I used `OBJREF` moniker for that. I'm going to check how it works with .NET remoting. – noseratio Apr 23 '14 at 09:54
-
1Searching `mscorlib.dll` (use `typeof(object).Assembly`) finds more classes like that. – Jeppe Stig Nielsen Apr 23 '14 at 09:57
-
@JeppeStigNielsen added (removing all `abstract` types, for clarity) – Marc Gravell Apr 23 '14 at 10:11
-
Wow! What an explanation! So simply put, if I use both [Serializable] and inherit from MarshalByRefObject at the same time OR only inherit from MarshalByRefObject then a reference of that object is passed always. And if I want to get a copy of that object then I have to mark it as [Serializable] ONLY. Is that right? – Gayan Jayasingha Apr 23 '14 at 10:37
-
1
MarshalByRefObject
is already marked as Serializable
, so this may seem a bit weird.
However, this is more about logically using the tools you have. Since MarshalByRefObject
s are actually accessed using proxies, they don't have a local state to serialize when you're using the proxy. That's the whole point of MarshalByRefObject
. When you're using serialization, you're transferring (or saving) the state - when marshalling by reference, you're only transferring a reference to the object. So serialization is a copy, while marshal by ref is still refering to the same object, even accross application domain boundaries.
Now, as far as I know, there's actually no check to make sure the object isn't serializable - however, in practice, when it's used from outside of its application domain, there really isn't anything to serialize.

- 62,244
- 7
- 97
- 116
-
It is marked `Serializable` in a special way to carry to reference to the remote proxy. – leppie Apr 23 '14 at 09:13
-
@leppie Yeah, that's what I thought. That's also the only information the proxy class really has, after all. – Luaan Apr 23 '14 at 09:16
-
Remark: The `SerializableAttribute` class has an `AttributeUsageAttribute` that sets `Inherited = false`, so it would seem relevant to apply `[Serializable]` again to derived classes. – Jeppe Stig Nielsen Apr 23 '14 at 09:46
-
@JeppeStigNielsen True, I've noticed that too. The thing is, you don't really want to serialize the `MarshalByRefObject`, because unless it's in your domain, it's not really there - you're only interacting with its proxy. However, if you want to allow serialization, you're better off using `ISerializable`, which allows you to do the serialization in the proper domain, and send just the results to the caller. I expect that using `[Serializable]` would either return bogus data, or only return the proxy's data (which is already in `MarshalByRefObject`. – Luaan Apr 23 '14 at 10:58