0

The main difference between built-in data types and user defined data types is that: built-in data types can accept literal values(values inserted into code directly,this process is also know as hard-codding).

So is it possible create custom data type same as boolean which accepts three values: yes/no/maybe WITHOUT USING enums.

such as following code:

MyCustomBoolean a = maybe;

I asked above question because i want to understand that built-in data types in C# are instructed in Core Language(such as C++ int,char...) or no?

---Update---

for the second question,let me ask a question to make the 2nd question more clear:

I know that for example string is alias of System.String but does pure string in C# works without System.String?

Amir
  • 1
  • 4
  • 1
    You can't change the syntax of the language (by definition). C# doesn't support user-defined literals (C++ does, but only to a [limited extent](http://en.cppreference.com/w/cpp/language/user_literal)). However, you can still get code that *looks* like that, for example by defining a variable of type `MyCustomBoolean` named `maybe`. – Cameron Sep 23 '14 at 18:29
  • 1
    In C#: No, not possible exactly. Roughly implict conversion operators comes closer though they won't give you any compile time safety. You need a type to convert from any other existing type. In your example `maybe` isn't a type. It means nothing to compiler. So that's not allowed. – Sriram Sakthivel Sep 23 '14 at 18:31
  • @Cameron I know that for example string is alias of System.String but does pure string in C# works without System.String? – Amir Sep 23 '14 at 18:32
  • @Cameron C++11 also has `constexpr` which is really powerful and seems to be what the OP is looking for. – Dai Sep 23 '14 at 18:33
  • @Amir without `System.String`, no `string` cannot work. They are the same thing. – Marc Gravell Sep 23 '14 at 18:33
  • 1
    As a workaround you could use a nullable boolean (`bool?`), where a `null` value indicates maybe. – Pierre-Luc Pineault Sep 23 '14 at 18:33
  • @Amir Obviously an alias to something else doesn't work without that something else. `System.String` is what has a whole bunch of special language support. You couldn't just implement your own string class, and have access to all of the features strings have, without that special language support. – Servy Sep 23 '14 at 18:34
  • @Servy So why System.String has access to these special features? It's true that it is part of BCL but i don't think that it is more than a compiled c# code?!?! – Amir Sep 23 '14 at 18:39
  • @Amir It has special functionality because that's how the language was designed. – Servy Sep 23 '14 at 18:41
  • @Servy so if we have source of string class,we can not do this? – Amir Sep 23 '14 at 18:42
  • @Amir That's exactly what I said. – Servy Sep 23 '14 at 18:44
  • @Servy , I was a C# programmer first but this is why i hate C#,because the integration of C# and .NET framework is really dirty but C++ provides all required data types in core language. But now i think that i should not think so much about these concepts. – Amir Sep 23 '14 at 18:46
  • @Amir If you think that C++ doesn't have special language support for a few few core types, such as strings, then you're mistaken, because it absolutely does. I don't think I've ever heard of a language (besides machine code) that *didn't* have special language support for strings. – Servy Sep 23 '14 at 18:48
  • @Servy but C++ string header implementation is not impossible,it is not magical because C++ supports C-style strings as default and this header has optimized the way of using it without any magical things. – Amir Sep 23 '14 at 18:50
  • @Amir C++ has special language support for string literals. There is no possible implementation of a type that could have string literals if that weren't already baked into the language. Additional code can utilize what is exposed through the compile time literals of the type and provide functionality for them, but it can't *create* them. This is the same in C#; the string type provides functionality for the objects created using the compile time string literals, but the code doesn't *create* the ability for compile time string literals. – Servy Sep 23 '14 at 18:55
  • @Servy i'm really confused! – Amir Sep 23 '14 at 18:56

3 Answers3

2

There are no ways to do this exactly as you've requested. You can however create constant fields in C# which can accomplish this result (named values) but only with the integral types or strings - in other words, the things you can already use for compile-time constants. This can be particularly useful for otherwise Magic Values.

public const string Maybe = "Maybe";
public const int Maybe = 0;

One way around this, though it will not be usable as a true constant, is to initialize static readonly fields or properties. For example

public static readonly MyCustomBoolean Maybe { get { return new MycustomBoolean(); } }
public static MyCustomBoolean Maybe = new MyCustomBoolean();
David
  • 10,458
  • 1
  • 28
  • 40
  • `but only with the integral types` No. You can use any compile time literals, to which there are some non-numeric types. – Servy Sep 23 '14 at 18:35
  • non-numeric, yes, but I mentioned Integral intentionally. Updating my answer with a link for clarity. – David Sep 23 '14 at 18:37
  • 1
    And I'm saying that that's wrong. There are plenty of compile time literals for types that are not on that list. You even have an example of one *right in your answer*. The correct statement is that a `const` identifier (note it's not actually a field) can be initialized to the value of any compile time literal. – Servy Sep 23 '14 at 18:40
  • OK, so yes, apparently strings don't count as "integral" – David Sep 23 '14 at 18:41
  • And strings aren't the only exception either. Feel free to look at the language specs if you want to see a more detailed explanation for what valid compile time literals are in C#. That said, the whole point of the question is asking how to define *his own* types of compile time literals of custom types that don't already have compile time literals. This doesn't answer that question. – Servy Sep 23 '14 at 18:43
0

You can have a nullable bool instead for this specific case. With typical operations like:

bool? b = null
if (b.HasValue)
if (b.Value)
b = true

Where the maybe would be null, or having HasValue == false.

Pieter21
  • 1,765
  • 1
  • 10
  • 22
0

Literals are a feature of the C# language. You cannot create new literals.

You might be interested in a different programming language such as Nemerle that allows you to create user defined literals such as this XML literal: https://github.com/rsdn/nemerle/wiki/XML-literals

Enums and constants usually fill the void for C#. For more complex structures you often see some flavor of fluent API being used.

Of course we can see the lack of this feature in C# meant that to provide a natural way to define queries meant the C# language spec needed to change to support LINQ. Had C# had similar meta programming features as Nemerle, then they could have accomplished the same goals as LINQ without changing the language syntax.

AaronLS
  • 37,329
  • 20
  • 143
  • 202
  • Yes! LINQ is a good example.But how LINQ does this actually with pure C# code? – Amir Sep 23 '14 at 18:41
  • @Amir There are no compile time literals used when it comes to using LINQ. I fail to see how LINQ is relevant here. – Servy Sep 23 '14 at 18:51
  • @Servy please take look at the following code: int[] array = { 1, 2, 3, 6, 7, 8 }; // Query expression. var elements = from element in array orderby element descending where element > 2 select element; – Amir Sep 23 '14 at 18:53
  • it uses words that c# does not have it in it core language. – Amir Sep 23 '14 at 18:54
  • @Amir Those words *are* in the core language. They're keywords, not compile time constant values, but they are also defined in the actual C# language specs as contextual keywords. They are not defined by LINQ, nor are the even specific to LINQ. Feel free to see the query comprehension section of the C# language specs to read about them yourself. – Servy Sep 23 '14 at 19:00
  • @Servy "They are not defined by LINQ" `(from x in db.People join y in db.Orders on ...`, lots of keywords introduced specifically for LINQ support, `from`, `on`, `join` all specific to LINQ. While LINQ statements are not literals, similar goal could have been accomplished had the language support user defined literals, and we could have implement query literals. Much like Nemerle allows user defined literals such as XML. User defined literals essentially allow you to build in compile time support for other embedded languages. – AaronLS Sep 23 '14 at 19:08
  • @AaronLS They were added to the language, by the language designers, for the sake of LINQ, but they are not defined by LINQ. There's a difference. They're also *not* specific to LINQ; other non-LINQ code can use those keywords to, if it wants to. Yes, the language designers could have provided support for user-defined compile time literals. It would be *super* hard to do, but I imagine it's possible, sure. C# doesn't have that though, so you'd have to use some other language besides C# if you want that feature. – Servy Sep 23 '14 at 19:10
  • @Servy "C# doesn't have that though, so you'd have to use some other language besides C# if you want that featuer." **I said that already in my answer** "You cannot create new literals.", "You might be interested in a different programming language such as Nemerle". – AaronLS Sep 23 '14 at 19:12
  • @Servy "not defined by LINQ." I never said that, I specifically stated the C# language spec changed to support LINQ by introducing new keywords for that purpose. You need to read the C# spec and the documentation on Language Integrated Query's – AaronLS Sep 23 '14 at 19:14
  • @AaronLS You're quite right that you didn't say they were defined by LINQ. Amir did, and it was his comment that I was replying to. – Servy Sep 23 '14 at 19:18
  • @Servy "@AaronLS They were added to the language, by the language designers, for the sake of LINQ, but they are not defined by LINQ" – AaronLS Sep 23 '14 at 20:25